diff --git a/.github/test-spec.yml b/.github/test-spec.yml new file mode 100644 index 000000000000..5fdf9c0ca782 --- /dev/null +++ b/.github/test-spec.yml @@ -0,0 +1,401 @@ +# This is the Jenkins ci variant of the .github/labler.yaml + +"CI-run-zephyr-twister": + - any: + - "!.github/**/*" + - "!doc/**/*" + - "!CODEOWNERS" + - "!LICENSE" + - "!**/*.rst" + - "!VERSION" + - "!submanifests/**/*" + - "!MAINTAINERS.yml" + - "!version.h.in" + - "!Jenkinsfile" + - "!**/*.md" + +"CI-iot-zephyr-lwm2m-test": + - "drivers/console/**/*" + - "drivers/flash/**/*" + - "subsys/dfu/boot/**/*" + - "subsys/net/ip/**/*" + - "subsys/net/lib/http/**/*" + - "subsys/net/lib/lwm2m//**/*" + - "subsys/net/**/*" + +"CI-iot-samples-test": + - "boards/nordic/nrf9160dk/**/*" + - "dts/arm/nordic/nrf9160*" + - "include/net/**/*" + - "subsys/net/lib/**/*" + +"CI-iot-libraries-test": + - "boards/nordic/nrf9160dk/**/*" + - "dts/arm/nordic/nrf9160*" + - "include/net/socket_ncs.h" + - "subsys/testsuite/ztest/**/*" + +"CI-lwm2m-test": null +# Not necessary to run tests on changes to this repo. + +"CI-boot-test": + - "boards/nordic/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "subsys/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "include/dfu/**/*" + - "samples/subsys/mgmt/mcumgr/smp_svr/**/*" + - "tests/boot/**/*" + - "tests/subsys/dfu/**/*" + - "tests/subsys/mgmt/mcumgr/**/*" + +"CI-dfu-test": + - "boards/nordic/**/*" + - "drivers/bluetooth/**/*" + - "drivers/console/**/*" + - "drivers/flash/**/*" + - "drivers/mbox/**/*" + - "drivers/serial/**/*" + - "drivers/spi/**/*" + - "dts/arm/nordic/nrf54h*" + - "dts/common/nordic/*" + - "dts/riscv/nordic/nrf54h*" + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "include/zephyr/**/*" + - "samples/subsys/mgmt/mcumgr/smp_svr/**/*" + - "scripts/west_commands/build.py" + - "scripts/west_commands/flash.py" + - "scripts/west_commands/runners/core.py" + - "scripts/west_commands/runners/nrf_common.py" + - "scripts/west_commands/runners/nrfutil.py" + - "soc/nordic/nrf54h/**/*" + - "subsys/bluetooth/**/*" + - "subsys/dfu/**/*" + - "subsys/logging/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "subsys/tracing/**/*" + +"CI-tfm-test": + - "boards/nordic/nrf5340dk/**/*" + - "boards/nordic/nrf9160dk/**/*" + - "drivers/entropy/*" + - "dts/arm/nordic/nrf5340*" + - "dts/arm/nordic/nrf9160*" + - "modules/trusted-firmware-m/**/*" + - "samples/tfm_integration/**/*" + +"CI-ble-test": + - any: + - "arch/arm/**/*" + - any: + - "drivers/bluetooth/**/*" + - any: + - "dts/arm/nordic/nrf5*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" + - any: + - "include/zephyr/bluetooth/**/*" + - "!include/zephyr/bluetooth/mesh/**/*" + - any: + - "boards/nordic/nrf5*" + - any: + - "soc/nordic/**/*" + - any: + - "subsys/pm/**/*" + +"CI-ble-samples-test": + - any: + - "drivers/bluetooth/**/*" + - any: + - "dts/arm/nordic/nrf5*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" + - any: + - "include/zephyr/bluetooth/**/*" + - "!include/zephyr/bluetooth/mesh/**/*" + - "samples/bluetooth/**/*" + +"CI-mesh-test": + - "subsys/bluetooth/mesh/**/*" + - "include/zephyr/bluetooth/mesh/**/*" + - "samples/bluetooth/mesh/**/*" + - "samples/bluetooth/mesh_demo/**/*" + - "samples/bluetooth/mesh_provisioner/**/*" + - "tests/bluetooth/mesh/**/*" + - "tests/bluetooth/mesh_shell/**/*" + +"CI-thingy91-test": + - "boards/nordic/nrf9160dk/**/*" + - "arch/x86/core/**/*" + - "arch/x86/include/**/*" + - "drivers/console/**/*" + - "drivers/ethernet/**/*" + - "drivers/flash/**/*" + - "drivers/hwinfo/**/*" + - "drivers/interrupt_controller/**/*" + - "drivers/net/**/*" + - "drivers/serial/**/*" + - "drivers/timer/**/*" + - "include/**/*" + - "kernel/**/*" + - "lib/libc/common/source/stdlib/**/*" + - "lib/libc/newlib/**/*" + - "lib/libc/picolibc/**/*" + - "lib/os/**/*" + - "lib/posix/**/*" + - "misc/**/*" + - "modules/mbedtls/**/*" + - "soc/x86/ia32/**/*" + - "subsys/fs/fcb/**/*" + - "subsys/logging/**/*" + - "subsys/net/**/*" + - "subsys/random/**/*" + - "subsys/settings/include/**/*" + - "subsys/settings/src/**/*" + - "subsys/stats/**/*" + - "subsys/storage/flash_map/**/*" + - "subsys/storage/stream/**/*" + - "subsys/tracing/**/*" + +"CI-desktop-test": + - "drivers/bluetooth/*" + - "subsys/bluetooth/*" + - "include/zephyr/bluetooth/*" + +"CI-crypto-test": + - "boards/nordic/nrf52840dk/**/*" + - "boards/nordic/nrf5340dk/**/*" + - "boards/nordic/nrf9160dk/**/*" + - "drivers/entropy/*" + - "drivers/serial/**/*" + - "dts/arm/nordic/nrf52840*" + - "dts/arm/nordic/nrf5340*" + - "dts/arm/nordic/nrf9160*" + - "include/drivers/serial/**/*" + - "modules/mbedtls/**/*" + +"CI-fem-test": + - "boards/nordic/**/*" + - "drivers/bluetooth/hci/**/*" + - "drivers/entropy/**/*" + - "dts/bindings/**/*" + - "include/zephyr/net/**/*" + - "include/zephyr/arch/**/*" + - "lib/libc/**/*" + - "lib/open-amp/**/*" + - "modules/hal_nordic/**/*" + - "modules/mbedtls/**/*" + - "modules/openthread/**/*" + - "modules/trusted-firmware-m/**/*" + - "samples/net/sockets/echo_*/**/*" + - "share/**/*" + - "soc/nordic/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + - "subsys/bluetooth/shell/**/*" + - "subsys/ipc/**/*" + - "Kconfig" + - "CMakeLists.txt" + +"CI-rs-test": + - "boards/nordic/**/*" + - "drivers/bluetooth/hci/**/*" + - "drivers/entropy/**/*" + - "dts/bindings/**/*" + - "include/zephyr/net/**/*" + - "include/zephyr/arch/**/*" + - "lib/libc/**/*" + - "lib/open-amp/**/*" + - "modules/hal_nordic/**/*" + - "modules/mbedtls/**/*" + - "modules/openthread/**/*" + - "modules/trusted-firmware-m/**/*" + - "samples/net/sockets/echo_*/**/*" + - "share/**/*" + - "soc/nordic/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + - "subsys/bluetooth/shell/**/*" + - "subsys/ipc/**/*" + - "Kconfig" + - "CMakeLists.txt" + +"CI-thread-test": + - "include/zephyr/net/**/*" + - "modules/mbedtls/**/*" + - "modules/openthread/**/*" + - "samples/net/openthread/**/*" + - "soc/nordic/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-nfc-test": + - "drivers/bluetooth/hci/**/*" + - "drivers/entropy/**/*" + - "drivers/flash/**/*" + - "drivers/mbox/**/*" + - "drivers/spi/**/*" + - "lib/crc/**/*" + - "modules/hal_nordic/**/*" + - "soc/nordic/**/*" + - "subsys/ipc/ipc_service/**/*" + - "subsys/fs/**/*" + - "subsys/mem_mgmt/**/*" + - "subsys/net/**/*" + - "subsys/random/**/*" + - "subsys/settings/**/*" + - "subsys/shell/**/*" + - "subsys/storage/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + +"CI-matter-test": + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "soc/nordic/**/*" + - "subsys/dfu/**/*" + - "subsys/settings/**/*" + - "subsys/net/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "drivers/net/**/*" + - "samples/bluetooth/hci_ipc/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" + +"CI-find-my-test": + - "boards/nordic/**/*" + - "drivers/bluetooth/**/*" + - "drivers/entropy/**/*" + - "drivers/flash/**/*" + - "drivers/usb/**/*" + - "drivers/regulator/**/*" + - "soc/nordic/**/*" + - "subsys/dfu/**/*" + - "subsys/fs/**/*" + - "subsys/ipc/**/*" + - "subsys/net/**/*" + - "subsys/random/**/*" + - "subsys/settings/**/*" + - "subsys/storage/**/*" + - "subsys/tracing/**/*" + - "subsys/usb/device/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + +"CI-rpc-test": + - "subsys/ipc/ipc_service/**/*" + - "subsys/random/**/*" + - "soc/nordic/nrf53/**/*" + +"CI-modemshell-test": + - "include/net/**/*" + - "include/posix/**/*" + - "include/shell/**/*" + - "drivers/net/**/*" + - "drivers/serial/**/*" + - "drivers/wifi/**/*" + - "subsys/shell/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-positioning-test": + - "include/net/**/*" + - "include/posix/**/*" + - "drivers/net/**/*" + - "drivers/wifi/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-cloud-test": + - "include/zephyr/dfu/**/*" + - "include/zephyr/net/**/*" + - "include/zephyr/posix/**/*" + - "include/zephyr/settings/**/*" + - "drivers/led/**/*" + - "drivers/net/**/*" + - "drivers/sensor/**/*" + - "drivers/serial/**/*" + - "drivers/wifi/**/*" + - "lib/posix/**/*" + - "soc/nordic/**/*" + - "subsys/dfu/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-wifi": + - "subsys/net/l2/wifi/**/*" + - "subsys/net/l2/ethernet/**/*" + +"CI-audio-test": + - "boards/nordic/nrf5340_audio_dk/**/*" + - "drivers/flash/**/*" + - "drivers/spi/**/*" + - "drivers/gpio/**/*" + - "drivers/i2c/**/*" + - "drivers/watchdog/**/*" + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "samples/bluetooth/hci_ipc/**/*" + - "soc/nordic/**/*" + - "subsys/bluetooth/audio/**/*" + - "subsys/bluetooth/host/**/*" + - "subsys/dfu/**/*" + - "subsys/fs/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "subsys/sd/**/*" + - "subsys/storage/**/*" + - "subsys/task_wdt/**/*" + - "subsys/usb/**/*" + - "subsys/zbus/**/*" + +"CI-pmic-samples-test": + - "samples/shields/npm1300_ek/**/*" + - "boards/shields/npm1300_ek/**/*" + - "**/**npm1300**/**" + - "drivers/regulator/regulator_common.c" + - "drivers/regulator/regulator_shell.c" + - "drivers/gpio/gpio_shell.c" + - "drivers/sensor/sensor_shell.c" + +"CI-test-low-level": + - "arch/**/*" + - "boards/nordic/nrf54*/**/*" + - "drivers/**/*" + - "dts/**/*" + - "include/zephyr/**/*" + - "kernel/**/*" + - "modules/hal_nordic/**/*" + - "samples/basic/blinky_pwm/**/*" + - "samples/basic/fade_led/**/*" + - "samples/boards/nrf/**/*" + - "samples/boards/nordic/**/*" + - "samples/drivers/adc/**/*" + - "samples/drivers/jesd216/**/*" + - "samples/drivers/mbox/**/*" + - "samples/drivers/soc_flash_nrf/**/*" + - "samples/drivers/spi_flash/**/*" + - "samples/drivers/watchdog/**/*" + - "samples/hello_world/**/*" + - "samples/sensor/**/*" + - "samples/subsys/ipc/**/*" + - "samples/subsys/logging/**/*" + - "samples/subsys/settings/**/*" + - "samples/subsys/usb/cdc_acm/**/*" + - "samples/subsys/usb/mass/**/*" + - "samples/synchronization/**/*" + - "subsys/logging/**/*" + - "subsys/settings/**/*" + - "tests/arch/**/*" + - "tests/boards/nrf/**/*" + - "tests/boards/nordic/**/*" + - "tests/drivers/**/*" + - "tests/kernel/**/*" diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml new file mode 100644 index 000000000000..61fc3a6c5bd3 --- /dev/null +++ b/.github/workflows/commit-tags.yml @@ -0,0 +1,31 @@ +name: Commit tags + +on: + pull_request: + types: [synchronize, opened, reopened, edited, labeled, unlabeled, + milestoned, demilestoned, assigned, unassigned, ready_for_review, + review_requested] + +permissions: + contents: read + +jobs: + commit_tags: + runs-on: ubuntu-22.04 + name: Run commit tags checks on patch series (PR) + steps: + - name: Update PATH for west + run: | + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Checkout the code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Run the commit tags + uses: nrfconnect/action-commit-tags@main + with: + target: . + upstream: zephyrproject-rtos/zephyr/main diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index 9d19b5a69e65..0e39baa4732d 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -34,8 +34,8 @@ jobs: git config --global user.name "Your Name" git remote -v # Ensure there's no merge commits in the PR - [[ "$(git rev-list --merges --count origin/${BASE_REF}..)" == "0" ]] || \ - (echo "::error ::Merge commits not allowed, rebase instead";false) + #[[ "$(git rev-list --merges --count origin/${BASE_REF}..)" == "0" ]] || \ + #(echo "::error ::Merge commits not allowed, rebase instead";false) rm -fr ".git/rebase-apply" rm -fr ".git/rebase-merge" git rebase origin/${BASE_REF} @@ -72,12 +72,9 @@ jobs: git log --pretty=oneline | head -n 10 # Increase rename limit to allow for large PRs git config diff.renameLimit 10000 - excludes="-e KconfigBasic -e SysbuildKconfigBasic -e ClangFormat" - # The signed-off-by check for dependabot should be skipped - if [ "${{ github.actor }}" == "dependabot[bot]" ]; then - excludes="$excludes -e Identity" - fi - ./scripts/ci/check_compliance.py --annotate $excludes -c origin/${BASE_REF}.. + ./scripts/ci/check_compliance.py --annotate -e KconfigBasic -e SysbuildKconfigBasic \ + -e Kconfig -e SysbuildKconfig -e KconfigBasicNoModules -e SysbuildKconfigBasicNoModules \ + -e ModulesMaintainers -c origin/${BASE_REF}.. - name: upload-results uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 diff --git a/.github/workflows/manifest-PR.yml b/.github/workflows/manifest-PR.yml new file mode 100644 index 000000000000..0f3bd738a36c --- /dev/null +++ b/.github/workflows/manifest-PR.yml @@ -0,0 +1,19 @@ +name: handle manifest PR +on: + pull_request_target: + types: [opened, synchronize, closed, reopened] + branches: + - main + +permissions: + contents: read + +jobs: + call-manifest-pr-action: + runs-on: ubuntu-latest + steps: + - name: handle manifest PR + uses: nrfconnect/action-manifest-pr@main + with: + token: ${{ secrets.NCS_GITHUB_TOKEN }} + manifest-pr-title-details: ${{ github.event.pull_request.title }} diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000000..3b9cf0022399 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,5 @@ +@Library("CI_LIB") _ + +def pipeline = new ncs.sdk_zephyr.Main() + +pipeline.run(JOB_NAME) diff --git a/Kconfig.zephyr b/Kconfig.zephyr index d8df86add4d3..d758a03baff4 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -6,7 +6,6 @@ # SPDX-License-Identifier: Apache-2.0 source "Kconfig.constants" -source "$(KCONFIG_ENV_FILE)" osource "$(APPLICATION_SOURCE_DIR)/VERSION" diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 0160330ac59f..aa0718740df8 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1147,7 +1147,6 @@ Documentation: - doc/images/Zephyr-Kite-in-tree.png - doc/index-tex.rst - doc/index.rst - - doc/kconfig.rst - doc/templates/sample.tmpl - doc/templates/board.tmpl - boards/index.rst diff --git a/arch/arm/core/cortex_m/pm_s2ram.c b/arch/arm/core/cortex_m/pm_s2ram.c index 81a4ae20a4f6..ce80c78a078a 100644 --- a/arch/arm/core/cortex_m/pm_s2ram.c +++ b/arch/arm/core/cortex_m/pm_s2ram.c @@ -28,7 +28,7 @@ __noinit #endif _cpu_context_t _cpu_context; -#ifndef CONFIG_PM_S2RAM_CUSTOM_MARKING +#ifndef CONFIG_HAS_PM_S2RAM_CUSTOM_MARKING /** * S2RAM Marker */ @@ -50,4 +50,4 @@ bool pm_s2ram_mark_check_and_clear(void) return false; } -#endif /* CONFIG_PM_S2RAM_CUSTOM_MARKING */ +#endif /* CONFIG_HAS_PM_S2RAM_CUSTOM_MARKING */ diff --git a/arch/arm/core/cortex_m/reset.S b/arch/arm/core/cortex_m/reset.S index b09391aaf0b5..85002c275f7c 100644 --- a/arch/arm/core/cortex_m/reset.S +++ b/arch/arm/core/cortex_m/reset.S @@ -35,6 +35,10 @@ GTEXT(z_arm_init_arch_hw_at_boot) #if defined(CONFIG_PM_S2RAM) GTEXT(arch_pm_s2ram_resume) #endif +#if defined(CONFIG_SOC_EARLY_RESET_HOOK) +GTEXT(soc_early_reset_hook) +#endif + /* * PACBTI Mask for CONTROL register: @@ -100,6 +104,10 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start) #endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */ +#if defined(CONFIG_SOC_EARLY_RESET_HOOK) + /* Call custom code that executes before any stack is set up or RAM memory is accessed */ + bl soc_early_reset_hook +#endif #if defined(CONFIG_PM_S2RAM) /* * Temporarily set MSP to interrupt stack so that arch_pm_s2ram_resume can diff --git a/arch/arm/core/mpu/arm_mpu_regions.c b/arch/arm/core/mpu/arm_mpu_regions.c index 0bf7a219c27d..383fd573513c 100644 --- a/arch/arm/core/mpu/arm_mpu_regions.c +++ b/arch/arm/core/mpu/arm_mpu_regions.c @@ -8,6 +8,9 @@ #include #include +#if USE_PARTITION_MANAGER +#include +#endif static const struct arm_mpu_region mpu_regions[] = { #ifdef CONFIG_XIP @@ -24,6 +27,14 @@ static const struct arm_mpu_region mpu_regions[] = { /* Region 1 */ MPU_REGION_ENTRY("SRAM_0", +#if USE_PARTITION_MANAGER + PM_SRAM_ADDRESS, +#if defined(CONFIG_ARMV8_M_BASELINE) || defined(CONFIG_ARMV8_M_MAINLINE) + REGION_RAM_ATTR(PM_SRAM_ADDRESS, PM_SRAM_SIZE)), +#else + REGION_RAM_ATTR(REGION_SRAM_SIZE)), +#endif +#else CONFIG_SRAM_BASE_ADDRESS, #if defined(CONFIG_ARMV8_M_BASELINE) || defined(CONFIG_ARMV8_M_MAINLINE) REGION_RAM_ATTR(CONFIG_SRAM_BASE_ADDRESS, \ @@ -31,6 +42,8 @@ static const struct arm_mpu_region mpu_regions[] = { #else REGION_RAM_ATTR(REGION_SRAM_SIZE)), #endif + +#endif /* USE_PARTITION_MANAGER */ }; const struct arm_mpu_config mpu_config = { diff --git a/arch/common/CMakeLists.txt b/arch/common/CMakeLists.txt index d817afa3d7fe..a764235130ed 100644 --- a/arch/common/CMakeLists.txt +++ b/arch/common/CMakeLists.txt @@ -109,6 +109,9 @@ if (CONFIG_GEN_ISR_TABLES) add_dependencies(isr_tables zephyr_generated_headers) target_link_libraries(isr_tables zephyr_interface) zephyr_library_link_libraries(isr_tables) + + zephyr_link_libraries($_sw_isr_table) + zephyr_link_libraries($_irq_vector_table) endif() if(CONFIG_COVERAGE) diff --git a/arch/riscv/core/irq_manage.c b/arch/riscv/core/irq_manage.c index 8ba7b615b422..3d18ec59dba3 100644 --- a/arch/riscv/core/irq_manage.c +++ b/arch/riscv/core/irq_manage.c @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef CONFIG_RISCV_HAS_PLIC #include @@ -75,3 +76,19 @@ int arch_irq_disconnect_dynamic(unsigned int irq, unsigned int priority, } #endif /* CONFIG_SHARED_INTERRUPTS */ #endif /* CONFIG_DYNAMIC_INTERRUPTS */ + +#ifdef CONFIG_PM +void arch_isr_direct_pm(void) +{ + unsigned int key; + + key = irq_lock(); + + if (_kernel.idle) { + _kernel.idle = 0; + pm_system_resume(); + } + + irq_unlock(key); +} +#endif diff --git a/boards/ezurio/bl54l15_dvk/Kconfig.defconfig b/boards/ezurio/bl54l15_dvk/Kconfig.defconfig index 78ec8fa7116a..2ff8fe6e3027 100644 --- a/boards/ezurio/bl54l15_dvk/Kconfig.defconfig +++ b/boards/ezurio/bl54l15_dvk/Kconfig.defconfig @@ -6,13 +6,6 @@ DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition -if BOARD_BL54L15_DVK_NRF54L10_CPUAPP || BOARD_BL54L15_DVK_NRF54L15_CPUAPP - -config ROM_START_OFFSET - default 0x800 if BOOTLOADER_MCUBOOT - -endif # BOARD_BL54L15_DVK_NRF54L10_CPUAPP || BOARD_BL54L15_DVK_NRF54L15_CPUAPP - if BOARD_BL54L15_DVK_NRF54L10_CPUAPP_NS || BOARD_BL54L15_DVK_NRF54L15_CPUAPP_NS config HAS_BT_CTLR diff --git a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp_ns_defconfig b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp_ns_defconfig index dea04c45f20c..e62b6fe90745 100644 --- a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp_ns_defconfig +++ b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp_ns_defconfig @@ -34,4 +34,4 @@ CONFIG_TFM_LOG_LEVEL_SILENCE=n # from the non secure application directly. This needs to be set # otherwise nrfx will try to configure them, resulting in a bus # fault. -CONFIG_SOC_NRF54LX_SKIP_CLOCK_CONFIG=y +CONFIG_NRF_SKIP_CLOCK_CONFIG=y diff --git a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp_ns_defconfig b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp_ns_defconfig index dea04c45f20c..e62b6fe90745 100644 --- a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp_ns_defconfig +++ b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp_ns_defconfig @@ -34,4 +34,4 @@ CONFIG_TFM_LOG_LEVEL_SILENCE=n # from the non secure application directly. This needs to be set # otherwise nrfx will try to configure them, resulting in a bus # fault. -CONFIG_SOC_NRF54LX_SKIP_CLOCK_CONFIG=y +CONFIG_NRF_SKIP_CLOCK_CONFIG=y diff --git a/boards/ezurio/bl54l15u_dvk/Kconfig.defconfig b/boards/ezurio/bl54l15u_dvk/Kconfig.defconfig index bb4934e7fd36..1e706cb66dd2 100644 --- a/boards/ezurio/bl54l15u_dvk/Kconfig.defconfig +++ b/boards/ezurio/bl54l15u_dvk/Kconfig.defconfig @@ -6,13 +6,6 @@ DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition -if BOARD_BL54L15U_DVK_NRF54L15_CPUAPP - -config ROM_START_OFFSET - default 0x800 if BOOTLOADER_MCUBOOT - -endif # BOARD_BL54L15U_DVK_NRF54L15_CPUAPP - if BOARD_BL54L15U_DVK_NRF54L15_CPUAPP_NS config HAS_BT_CTLR diff --git a/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp_ns_defconfig b/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp_ns_defconfig index dea04c45f20c..e62b6fe90745 100644 --- a/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp_ns_defconfig +++ b/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp_ns_defconfig @@ -34,4 +34,4 @@ CONFIG_TFM_LOG_LEVEL_SILENCE=n # from the non secure application directly. This needs to be set # otherwise nrfx will try to configure them, resulting in a bus # fault. -CONFIG_SOC_NRF54LX_SKIP_CLOCK_CONFIG=y +CONFIG_NRF_SKIP_CLOCK_CONFIG=y diff --git a/boards/index.rst b/boards/index.rst index 3cc92770cfeb..2ffe426fc24b 100644 --- a/boards/index.rst +++ b/boards/index.rst @@ -12,33 +12,8 @@ template available under :zephyr_file:`doc/templates/board.tmpl`. Shields are hardware add-ons that can be stacked on top of a board to add extra functionality. Refer to the :ref:`shield_porting_guide` for more information on how to port a shield. -.. admonition:: Search Tips - :class: dropdown - - * Use the form below to filter the list of supported boards and shields. If a field is left - empty, it will not be used in the filtering process. - - * Filtering by name and vendor is available for both boards and shields. The rest of the fields - apply only to boards. - - * A board/shield must meet **all** criteria selected across different fields. For example, if you - select both a vendor and an architecture, only boards that match both will be displayed. Within - a single field, selecting multiple options (such as two architectures) will show boards - matching **either** option. - - * The list of supported hardware features for each board is automatically generated using - information from the Devicetree. It may not be reflecting the full list of supported features - since some of them may not be enabled by default. - - * Can't find your exact board? Don't worry! If a similar board with the same or a closely related - MCU exists, you can use it as a :ref:`starting point ` for adding - support for your own board. - .. toctree:: :maxdepth: 2 :glob: - :hidden: */index - -.. zephyr:board-catalog:: diff --git a/boards/nordic/nrf54h20dk/Kconfig.defconfig b/boards/nordic/nrf54h20dk/Kconfig.defconfig index 069ed7b6eba6..c11d3ef63e1f 100644 --- a/boards/nordic/nrf54h20dk/Kconfig.defconfig +++ b/boards/nordic/nrf54h20dk/Kconfig.defconfig @@ -13,6 +13,7 @@ config MAX_THREAD_BYTES default 3 if USERSPACE config ROM_START_OFFSET + default 0 if NCS_MCUBOOT_BOOTLOADER_SIGN_MERGED_BINARY default 0x800 if BOOTLOADER_MCUBOOT if !USE_DT_CODE_PARTITION @@ -39,6 +40,7 @@ config MAX_THREAD_BYTES default 3 if USERSPACE config ROM_START_OFFSET + default 0 if NCS_MCUBOOT_BOOTLOADER_SIGN_MERGED_BINARY default 0x800 if BOOTLOADER_MCUBOOT endif # BOARD_NRF54H20DK_NRF54H20_CPURAD diff --git a/boards/nordic/nrf54h20dk/Kconfig.sysbuild b/boards/nordic/nrf54h20dk/Kconfig.sysbuild new file mode 100644 index 000000000000..29bd62b49927 --- /dev/null +++ b/boards/nordic/nrf54h20dk/Kconfig.sysbuild @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NRF54H20DK_NRF54H20_CPURAD + +config NRF_DEFAULT_EMPTY + default y + +endif # BOARD_NRF54H20DK_NRF54H20_CPURAD diff --git a/boards/nordic/nrf54h20dk/board.yml b/boards/nordic/nrf54h20dk/board.yml index 2d3d40c20e0b..1a505729f99c 100644 --- a/boards/nordic/nrf54h20dk/board.yml +++ b/boards/nordic/nrf54h20dk/board.yml @@ -14,3 +14,43 @@ board: default: "0.9.0" revisions: - name: "0.9.0" +runners: + run_once: + '--recover': + - runners: + - nrfutil + run: first + groups: + - boards: + - nrf54h20dk@0.9.0/nrf54h20/cpuapp + - nrf54h20dk@0.9.0/nrf54h20/cpurad + - nrf54h20dk@0.9.0/nrf54h20/cpuppr + - nrf54h20dk@0.9.0/nrf54h20/cpuppr/xip + - nrf54h20dk@0.9.0/nrf54h20/cpuflpr + - nrf54h20dk@0.9.0/nrf54h20/cpuflpr/xip + '--erase': + - runners: + - jlink + - nrfutil + run: first + groups: + - boards: + - nrf54h20dk@0.9.0/nrf54h20/cpuapp + - nrf54h20dk@0.9.0/nrf54h20/cpurad + - nrf54h20dk@0.9.0/nrf54h20/cpuppr + - nrf54h20dk@0.9.0/nrf54h20/cpuppr/xip + - nrf54h20dk@0.9.0/nrf54h20/cpuflpr + - nrf54h20dk@0.9.0/nrf54h20/cpuflpr/xip + '--reset': + - runners: + - jlink + - nrfutil + run: last + groups: + - boards: + - nrf54h20dk@0.9.0/nrf54h20/cpuapp + - nrf54h20dk@0.9.0/nrf54h20/cpurad + - nrf54h20dk@0.9.0/nrf54h20/cpuppr + - nrf54h20dk@0.9.0/nrf54h20/cpuppr/xip + - nrf54h20dk@0.9.0/nrf54h20/cpuflpr + - nrf54h20dk@0.9.0/nrf54h20/cpuflpr/xip diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index e14426c59fc8..eafaf69b3989 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -174,5 +174,34 @@ 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/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi index f62df87dfe26..0e2ab313df9b 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi @@ -138,4 +138,15 @@ low-power-enable; }; }; + + /omit-if-no-ref/ tpiu_default: tpiu_default { + group1 { + psels = , + , + , + , + ; + nordic,drive-mode = ; + }; + }; }; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index ba22403a9acd..e2d5b08cd300 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -18,7 +18,7 @@ chosen { zephyr,console = &uart136; - zephyr,code-partition = &slot0_partition; + zephyr,code-partition = &cpuapp_slot0_partition; zephyr,flash = &mram1x; zephyr,sram = &cpuapp_data; zephyr,shell-uart = &uart136; @@ -27,6 +27,7 @@ zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,canbus = &can120; + zephyr,entropy = &psa_rng; }; aliases { @@ -42,6 +43,8 @@ sw3 = &button3; ipc-to-cpusys = &cpuapp_cpusys_ipc; watchdog0 = &wdt010; + mcuboot-button0 = &button0; + mcuboot-led0 = &led0; }; buttons { @@ -107,6 +110,11 @@ pwms = <&pwm130 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; }; }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; }; &cpuapp_bellboard { @@ -187,6 +195,8 @@ slot0_partition: &cpuapp_slot0_partition { label = "image-0"; }; +secondary_app_partition: &cpuapp_slot1_partition {}; + slot1_partition: &cpuapp_slot1_partition { label = "image-1"; }; @@ -335,16 +345,37 @@ zephyr_udc0: &usbhs { status = "okay"; }; -/* Trim this RAM block for making room on all run-time common S2RAM cpu context. */ +/* Trim this RAM block for power management related features. */ &cpuapp_ram0 { - reg = <0x22000000 (DT_SIZE_K(32)-32)>; - ranges = <0x0 0x22000000 (0x8000-0x20)>; + reg = <0x22000000 (DT_SIZE_K(32) - 256)>; + ranges = <0x0 0x22000000 (0x8000 - 0x100)>; }; / { soc { + /* cache control functions - must be executed from local SRAM */ + pm_ramfunc: cpuapp_s2ram@22007f00 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x22007f00 192>; + zephyr,memory-region = "PMLocalRamfunc"; + }; + + /* temporary stack for S2RAM resume logic */ + pm_s2ram_stack: cpuapp_s2ram_stack@22007fc8 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x22007fc8 16>; + zephyr,memory-region = "pm_s2ram_stack"; + }; + + /* run-time common mcuboot S2RAM support section */ + mcuboot_s2ram: cpuapp_s2ram@22007fd8 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x22007fd8 8>; + zephyr,memory-region = "mcuboot_s2ram_context"; + }; + /* run-time common S2RAM cpu context RAM */ - pm_s2ram: cpuapp_s2ram@22007fe0 { + pm_s2ram: cpuapp_s2ram@22007fe0 { compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x22007fe0 32>; zephyr,memory-region = "pm_s2ram_context"; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_0_9_0.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_0_9_0.yaml index 60f22350504d..87fe8c68ba91 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_0_9_0.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_0_9_0.yaml @@ -11,6 +11,7 @@ sysbuild: true ram: 62 flash: 62 supported: + - adc - counter - gpio - i2c diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip_0_9_0.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip_0_9_0.yaml index 7198a379a9c9..58c6473538d9 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip_0_9_0.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip_0_9_0.yaml @@ -12,3 +12,4 @@ ram: 62 flash: 64 supported: - gpio + - spi diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts index 5473d9a7405a..4a8f5972227f 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts @@ -28,12 +28,18 @@ zephyr,ieee802154 = &cpurad_ieee802154; zephyr,bt-hci-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; + zephyr,entropy = &psa_rng; }; aliases { ipc-to-cpusys = &cpurad_cpusys_ipc; resetinfo = &cpurad_resetinfo; }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; }; &cpurad_bellboard { @@ -85,6 +91,8 @@ slot0_partition: &cpurad_slot0_partition { label = "image-0"; }; +secondary_app_partition: &cpurad_slot1_partition {}; + slot1_partition: &cpurad_slot1_partition { label = "image-1"; }; @@ -116,3 +124,20 @@ slot1_partition: &cpurad_slot1_partition { zephyr_udc0: &usbhs { status = "disabled"; }; + +/* Trim this RAM block for power management related features. */ +&cpurad_ram0 { + reg = <0x23000000 (DT_SIZE_K(192) - 192)>; + ranges = <0x0 0x23000000 (0x30000 - 0xC0)>; +}; + +/ { + soc { + /* cache control functions - must be executed from RAM */ + pm_ramfunc: cpurad_s2ram@2302ff40 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2302ff40 192>; + zephyr,memory-region = "PMLocalRamfunc"; + }; + }; +}; diff --git a/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript index 9738ec77f437..d79c93417455 100644 --- a/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript +++ b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + __constant U32 _CPUCONF_ADDR = 0x52011000; __constant U32 _CPUCONF_CPUWAIT_OFFSET = 0x50C; @@ -5,32 +11,17 @@ __constant U32 _CPUCONF_CPUWAIT_OFFSET = 0x50C; __constant U32 _ATBFUNNEL211_ADDR = 0xBF04D000; __constant U32 _ATBFUNNEL212_ADDR = 0xBF04E000; __constant U32 _ATBFUNNEL_CTRLREG_OFFSET = 0x0; +__constant U32 _ATBFUNNEL_HOLDTIME_MASK = 0x700; __constant U32 _HOLDTIME_4 = 0x300; -__constant U32 _ENS0 = 0x1; -__constant U32 _ENS1 = 0x2; -__constant U32 _ENS2 = 0x4; +__constant U32 _ENS0 = 0x1; // Application Core +__constant U32 _ENS1 = 0x2; // Radio Core // ATBREPLICATOR __constant U32 _ATBREPLICATOR212_ADDR = 0xBF04A000; __constant U32 _ATBREPLICATOR213_ADDR = 0xBF04B000; __constant U32 _ATBREPLICATOR_IDFILTER0_OFFSET = 0x0; __constant U32 _ATBREPLICATOR_IDFILTER1_OFFSET = 0x4; -__constant U32 _ID_NONE = 0xFFFFFFFF; -__constant U32 _ID1x = 0xFFFFFFFD; - -// TSGEN -__constant U32 _TSGEN_ADDR = 0xBF041000; -__constant U32 _TSGEN_CNTCR_OFFSET = 0x0; -__constant U32 _TSGEN_CNTFID0_OFFSET = 0x20; -// Clock rate = TDD Freq. / 8 -__constant U32 _TS_CLOCKRATE = 40000000; - -// CTI -__constant U32 _CTI210_ADDR = 0xBF046000; -__constant U32 _CTICONTROL_OFFSET = 0x0; -__constant U32 _CTIOUTEN_OFFSET = 0xA0; -__constant U32 _CTIGATE_OFFSET = 0x140; -__constant U32 _TPIU_FLUSH_TRIG = 0x2; +__constant U32 _ATBREPLICATOR_IDFILTER_ETM = 0x2; // ETM has 0x10 TRACEID // TPIU __constant U32 _TPIU_ADDR = 0xBF043000; @@ -43,30 +34,10 @@ __constant U32 _ENFTC = 0x1; __constant U32 _TPIU_SYNC_FRAME_COUNT = 0x8; __constant U32 _CURRENTPORTSIZE_4 = 0x8; -// TDDCONF -__constant U32 _TDDCONF_ADDR = 0xBF001000; -__constant U32 _TRACEPORTSPEED_OFFSET = 0x408; -__constant U32 _SPEED80MHZ = 0x0; - // CoreSight general -__constant U32 _CORESIGHT_CLAIMSET_OFFSET = 0xFA0; -__constant U32 _CORESIGHT_CLAIMCLR_OFFSET = 0xFA4; __constant U32 _CORESIGHT_LAR_OFFSET = 0xFB0; __constant U32 _CORESIGHT_UNLOCK_KEY = 0xC5ACCE55; -// GPIO P7 -__constant U32 _P7_ADDR = 0x5F938E00; -__constant U32 _PIN_CNF3_OFFSET = 0x8C; -__constant U32 _PIN_CNF4_OFFSET = 0x90; -__constant U32 _PIN_CNF5_OFFSET = 0x94; -__constant U32 _PIN_CNF6_OFFSET = 0x98; -__constant U32 _PIN_CNF7_OFFSET = 0x9C; -__constant U32 _PIN_CNF_TPIU_CLOCK_VALUE = 0x80000503; -__constant U32 _PIN_CNF_TPIU_DATA_VALUE = 0x00000503; - -// Settings -__constant U32 _DEBUGGER_CLAIM_MASK = 0x2; - // Used to check if we have already set up tracing int _needCoresightSetup = 1; @@ -82,68 +53,59 @@ void _CSLock(U32 addr) JLINK_MEM_WriteU32(addr + _CORESIGHT_LAR_OFFSET, 0); } -// Set claim bits in the CoreSight peripheral to indicate to the firmware that it -// has been configured by the host debugger -void _CSClaim(U32 addr) -{ - JLINK_MEM_WriteU32(addr + _CORESIGHT_CLAIMSET_OFFSET, _DEBUGGER_CLAIM_MASK); -} - // Set up CoreSight and other necessary configuration so to enable ETM -> TPIU tracing. int _SetupETMTPIUTrace(void) { + U32 ctrlreg_old; + U32 ctrlreg_new; + U32 idfilter0_old; + U32 idfilter1_old; + U32 idfilter0_new; + U32 idfilter1_new; + // Set up ATB funnels/replicators to route ApplicationDomain ETM to TPIU + _CSUnlock(_ATBFUNNEL212_ADDR); - JLINK_MEM_WriteU32(_ATBFUNNEL212_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, _HOLDTIME_4 | _ENS0); - _CSClaim(_ATBFUNNEL212_ADDR); + ctrlreg_old = JLINK_MEM_ReadU32(_ATBFUNNEL212_ADDR + _ATBFUNNEL_CTRLREG_OFFSET); + ctrlreg_new = (ctrlreg_old & ~_ATBFUNNEL_HOLDTIME_MASK) | _HOLDTIME_4 | _ENS0; + JLINK_MEM_WriteU32(_ATBFUNNEL212_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, ctrlreg_new); _CSLock(_ATBFUNNEL212_ADDR); _CSUnlock(_ATBREPLICATOR212_ADDR); - JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, _ID_NONE); - JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, _ID1x); - _CSLock(_ATBREPLICATOR212_ADDR); - _CSClaim(_ATBREPLICATOR212_ADDR); + idfilter0_old = JLINK_MEM_ReadU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET); + idfilter1_old = JLINK_MEM_ReadU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET); + + idfilter0_new = idfilter0_old | _ATBREPLICATOR_IDFILTER_ETM; // SET for output 0 + idfilter1_new = idfilter1_old & ~_ATBREPLICATOR_IDFILTER_ETM; // CLEAR for output 1 + + JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, idfilter0_new); + JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, idfilter1_new); _CSLock(_ATBREPLICATOR212_ADDR); _CSUnlock(_ATBFUNNEL211_ADDR); - JLINK_MEM_WriteU32(_ATBFUNNEL211_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, _HOLDTIME_4 | _ENS0); - _CSClaim(_ATBFUNNEL211_ADDR); + ctrlreg_old = JLINK_MEM_ReadU32(_ATBFUNNEL211_ADDR + _ATBFUNNEL_CTRLREG_OFFSET); + ctrlreg_new = (ctrlreg_old & ~_ATBFUNNEL_HOLDTIME_MASK) | _HOLDTIME_4 | _ENS0; + JLINK_MEM_WriteU32(_ATBFUNNEL211_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, ctrlreg_new); _CSLock(_ATBFUNNEL211_ADDR); _CSUnlock(_ATBREPLICATOR213_ADDR); - JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, _ID1x); - JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, _ID_NONE); - _CSClaim(_ATBREPLICATOR213_ADDR); - _CSLock(_ATBREPLICATOR213_ADDR); + idfilter0_old = JLINK_MEM_ReadU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET); + idfilter1_old = JLINK_MEM_ReadU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET); - // Configure timestamp generator for the correct clock rate - JLINK_MEM_WriteU32(_TSGEN_ADDR + _TSGEN_CNTFID0_OFFSET, _TS_CLOCKRATE); - JLINK_MEM_WriteU32(_TSGEN_ADDR + _TSGEN_CNTCR_OFFSET, 1); - _CSClaim(_TSGEN_ADDR); + idfilter0_new = idfilter0_old & ~_ATBREPLICATOR_IDFILTER_ETM; // CLEAR for output 0 + idfilter1_new = idfilter1_old | _ATBREPLICATOR_IDFILTER_ETM; // SET for output 1 - // Configure CTI1 for TPIU formatter flushing - _CSUnlock(_CTI210_ADDR); - JLINK_MEM_WriteU32(_CTI210_ADDR + _CTIOUTEN_OFFSET, _TPIU_FLUSH_TRIG); - JLINK_MEM_WriteU32(_CTI210_ADDR + _CTIGATE_OFFSET, _TPIU_FLUSH_TRIG); - JLINK_MEM_WriteU32(_CTI210_ADDR + _CTICONTROL_OFFSET, 1); - _CSClaim(_CTI210_ADDR); - _CSLock(_CTI210_ADDR); + JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, idfilter0_new); + JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, idfilter1_new); + _CSLock(_ATBREPLICATOR213_ADDR); // Configure TPIU for port size 4, continuous formatting _CSUnlock(_TPIU_ADDR); JLINK_MEM_WriteU32(_TPIU_ADDR + _CURRENTPORTSIZE_OFFSET, _CURRENTPORTSIZE_4); JLINK_MEM_WriteU32(_TPIU_ADDR + _FFCR_OFFSET, _ENFCONT | _FONFLIN | _ENFTC); JLINK_MEM_WriteU32(_TPIU_ADDR + _FSCR_OFFSET, _TPIU_SYNC_FRAME_COUNT); - _CSClaim(_TPIU_ADDR); _CSLock(_TPIU_ADDR); - // Configure the trace pins - JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF3_OFFSET, _PIN_CNF_TPIU_CLOCK_VALUE); - JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF4_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); - JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF5_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); - JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF6_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); - JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF7_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); - return 0; } @@ -155,6 +117,19 @@ int ConfigTargetSettings(void) // Adjust trace sample delay to compensate for timing when using 320MHz JLINK_ExecCommand("TraceSampleAdjust TD = 1000"); + JLINK_ExecCommand("CORESIGHT_SetTPIUBaseAddr = 0xBF043000"); + + return 0; +} + +int StartTPIU(void) +{ + /* We sort this ourselves in _SetupETMTPIUTrace, don't let JLink touch it */ + return 0; +} + +int StopTPIU(void) +{ return 0; } @@ -169,6 +144,11 @@ int OnTraceStart(void) return 0; } +int AfterResetTarget(void) +{ + _needCoresightSetup = 1; + return 0; +} int SetupTarget(void) { @@ -179,3 +159,8 @@ int SetupTarget(void) return 0; } + +int InitEMU(void) { + JLINK_ExecCommand("EnableLowPowerHandlingMode"); + return 0; +} diff --git a/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript b/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript index e1861ae8c972..2ff7f6c160e3 100644 --- a/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript +++ b/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript @@ -1,11 +1,153 @@ -__constant U32 _CPUCONF_ADDR = 0x53011000; +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +__constant U32 _CPUCONF_ADDR = 0x52011000; __constant U32 _CPUCONF_CPUWAIT_OFFSET = 0x50C; +// ATBFUNNEL +__constant U32 _ATBFUNNEL211_ADDR = 0xBF04D000; +__constant U32 _ATBFUNNEL212_ADDR = 0xBF04E000; +__constant U32 _ATBFUNNEL_CTRLREG_OFFSET = 0x0; +__constant U32 _ATBFUNNEL_HOLDTIME_MASK = 0x700; +__constant U32 _HOLDTIME_4 = 0x300; +__constant U32 _ENS0 = 0x1; // Application Core +__constant U32 _ENS1 = 0x2; // Radio Core + +// ATBREPLICATOR +__constant U32 _ATBREPLICATOR212_ADDR = 0xBF04A000; +__constant U32 _ATBREPLICATOR213_ADDR = 0xBF04B000; +__constant U32 _ATBREPLICATOR_IDFILTER0_OFFSET = 0x0; +__constant U32 _ATBREPLICATOR_IDFILTER1_OFFSET = 0x4; +__constant U32 _ATBREPLICATOR_IDFILTER_ETM = 0x2; // ETM has 0x10 TRACEID + +// TPIU +__constant U32 _TPIU_ADDR = 0xBF043000; +__constant U32 _CURRENTPORTSIZE_OFFSET = 0x4; +__constant U32 _FFCR_OFFSET = 0x304; +__constant U32 _FSCR_OFFSET = 0x308; +__constant U32 _ENFCONT = 0x02; +__constant U32 _FONFLIN = 0x10; +__constant U32 _ENFTC = 0x1; +__constant U32 _TPIU_SYNC_FRAME_COUNT = 0x8; +__constant U32 _CURRENTPORTSIZE_4 = 0x8; + +// CoreSight general +__constant U32 _CORESIGHT_LAR_OFFSET = 0xFB0; +__constant U32 _CORESIGHT_UNLOCK_KEY = 0xC5ACCE55; + +// Used to check if we have already set up tracing +int _needCoresightSetup = 1; + +// Unlock a CoreSight peripheral +void _CSUnlock(U32 addr) +{ + JLINK_MEM_WriteU32(addr + _CORESIGHT_LAR_OFFSET, _CORESIGHT_UNLOCK_KEY); +} + +// Lock a CoreSight peripheral +void _CSLock(U32 addr) +{ + JLINK_MEM_WriteU32(addr + _CORESIGHT_LAR_OFFSET, 0); +} + +// Set up CoreSight and other necessary configuration so to enable ETM -> TPIU tracing. +int _SetupETMTPIUTrace(void) +{ + U32 ctrlreg_old; + U32 ctrlreg_new; + U32 idfilter0_old; + U32 idfilter1_old; + U32 idfilter0_new; + U32 idfilter1_new; + + // Set up ATB funnels/replicators to route ApplicationDomain ETM to TPIU + + _CSUnlock(_ATBFUNNEL212_ADDR); + ctrlreg_old = JLINK_MEM_ReadU32(_ATBFUNNEL212_ADDR + _ATBFUNNEL_CTRLREG_OFFSET); + ctrlreg_new = (ctrlreg_old & ~_ATBFUNNEL_HOLDTIME_MASK) | _HOLDTIME_4 | _ENS1; + JLINK_MEM_WriteU32(_ATBFUNNEL212_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, ctrlreg_new); + _CSLock(_ATBFUNNEL212_ADDR); + + _CSUnlock(_ATBREPLICATOR212_ADDR); + idfilter0_old = JLINK_MEM_ReadU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET); + idfilter1_old = JLINK_MEM_ReadU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET); + + idfilter0_new = idfilter0_old | _ATBREPLICATOR_IDFILTER_ETM; // SET for output 0 + idfilter1_new = idfilter1_old & ~_ATBREPLICATOR_IDFILTER_ETM; // CLEAR for output 1 + + JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, idfilter0_new); + JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, idfilter1_new); + _CSLock(_ATBREPLICATOR212_ADDR); + + _CSUnlock(_ATBFUNNEL211_ADDR); + ctrlreg_old = JLINK_MEM_ReadU32(_ATBFUNNEL211_ADDR + _ATBFUNNEL_CTRLREG_OFFSET); + ctrlreg_new = (ctrlreg_old & ~_ATBFUNNEL_HOLDTIME_MASK) | _HOLDTIME_4 | _ENS1; + JLINK_MEM_WriteU32(_ATBFUNNEL211_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, ctrlreg_new); + _CSLock(_ATBFUNNEL211_ADDR); + + _CSUnlock(_ATBREPLICATOR213_ADDR); + idfilter0_old = JLINK_MEM_ReadU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET); + idfilter1_old = JLINK_MEM_ReadU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET); + + idfilter0_new = idfilter0_old & ~_ATBREPLICATOR_IDFILTER_ETM; // CLEAR for output 0 + idfilter1_new = idfilter1_old | _ATBREPLICATOR_IDFILTER_ETM; // SET for output 1 + + JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, idfilter0_new); + JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, idfilter1_new); + _CSLock(_ATBREPLICATOR213_ADDR); + + // Configure TPIU for port size 4, continuous formatting + _CSUnlock(_TPIU_ADDR); + JLINK_MEM_WriteU32(_TPIU_ADDR + _CURRENTPORTSIZE_OFFSET, _CURRENTPORTSIZE_4); + JLINK_MEM_WriteU32(_TPIU_ADDR + _FFCR_OFFSET, _ENFCONT | _FONFLIN | _ENFTC); + JLINK_MEM_WriteU32(_TPIU_ADDR + _FSCR_OFFSET, _TPIU_SYNC_FRAME_COUNT); + _CSLock(_TPIU_ADDR); + + return 0; +} + int ConfigTargetSettings(void) { JLINK_ExecCommand("CORESIGHT_AddAP = Index=1 Type=AHB-AP"); CORESIGHT_IndexAHBAPToUse = 1; + // Adjust trace sample delay to compensate for timing when using 320MHz + JLINK_ExecCommand("TraceSampleAdjust TD = 1000"); + + JLINK_ExecCommand("CORESIGHT_SetTPIUBaseAddr = 0xBF043000"); + + return 0; +} + +int StartTPIU(void) +{ + /* We sort this ourselves in _SetupETMTPIUTrace, don't let JLink touch it */ + return 0; +} + +int StopTPIU(void) +{ + return 0; +} + + +int OnTraceStart(void) +{ + // Set up CoreSight if not already configured + if (_needCoresightSetup) { + _SetupETMTPIUTrace(); + _needCoresightSetup = 0; + } + + return 0; +} + +int AfterResetTarget(void) +{ + _needCoresightSetup = 1; return 0; } @@ -18,3 +160,8 @@ int SetupTarget(void) return 0; } + +int InitEMU(void) { + JLINK_ExecCommand("EnableLowPowerHandlingMode"); + return 0; +} diff --git a/boards/nordic/nrf54l15dk/Kconfig.defconfig b/boards/nordic/nrf54l15dk/Kconfig.defconfig index 49e38070a01a..f57b30c2c42d 100644 --- a/boards/nordic/nrf54l15dk/Kconfig.defconfig +++ b/boards/nordic/nrf54l15dk/Kconfig.defconfig @@ -4,15 +4,6 @@ config HW_STACK_PROTECTION default ARCH_HAS_STACK_PROTECTION -if BOARD_NRF54L15DK_NRF54L05_CPUAPP || BOARD_NRF54L15DK_NRF54L10_CPUAPP || \ - BOARD_NRF54L15DK_NRF54L15_CPUAPP - -config ROM_START_OFFSET - default 0x800 if BOOTLOADER_MCUBOOT - -endif # BOARD_NRF54L15DK_NRF54L05_CPUAPP || BOARD_NRF54L15DK_NRF54L10_CPUAPP || \ - # BOARD_NRF54L15DK_NRF54L15_CPUAPP - if BOARD_NRF54L15DK_NRF54L15_CPUAPP_NS || BOARD_NRF54L15DK_NRF54L10_CPUAPP_NS config BOARD_NRF54L15DK diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns_defconfig b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns_defconfig index d9f869918bfe..a0a4a0c63ac6 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns_defconfig +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns_defconfig @@ -32,4 +32,4 @@ CONFIG_TFM_LOG_LEVEL_SILENCE=n # from the non secure application directly. This needs to be set # otherwise nrfx will try to configure them, resulting in a bus # fault. -CONFIG_SOC_NRF54LX_SKIP_CLOCK_CONFIG=y +CONFIG_NRF_SKIP_CLOCK_CONFIG=y diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.yaml b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.yaml index e23a2a0073a9..6447d9d789bd 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.yaml +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.yaml @@ -17,8 +17,8 @@ supported: - dmic - gpio - i2c + - i2s - pwm - retained_mem - spi - watchdog - - i2s diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns.yaml b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns.yaml index 43bd7c8f2445..cff1b1970d39 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns.yaml +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns.yaml @@ -12,12 +12,12 @@ ram: 256 flash: 1524 supported: - adc + - counter - gpio - i2c + - i2s + - pwm - spi - - counter - watchdog - - adc - - i2s vendor: nordic sysbuild: true diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns_defconfig b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns_defconfig index d9f869918bfe..a0a4a0c63ac6 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns_defconfig +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns_defconfig @@ -32,4 +32,4 @@ CONFIG_TFM_LOG_LEVEL_SILENCE=n # from the non secure application directly. This needs to be set # otherwise nrfx will try to configure them, resulting in a bus # fault. -CONFIG_SOC_NRF54LX_SKIP_CLOCK_CONFIG=y +CONFIG_NRF_SKIP_CLOCK_CONFIG=y diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuflpr.dts b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuflpr.dts index 2bc4ba292bed..eae0b605eb4b 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuflpr.dts +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuflpr.dts @@ -8,6 +8,8 @@ #include #include "nrf54l15dk_common.dtsi" +/delete-node/ &cpuflpr_sram; + / { model = "Nordic nRF54L15 DK nRF54L15 FLPR MCU"; compatible = "nordic,nrf54l15dk_nrf54l15-cpuflpr"; @@ -19,13 +21,16 @@ zephyr,flash = &cpuflpr_rram; zephyr,sram = &cpuflpr_sram; }; -}; -&cpuflpr_sram { - status = "okay"; - /* size must be increased due to booting from SRAM */ - reg = <0x20028000 DT_SIZE_K(96)>; - ranges = <0x0 0x20028000 0x18000>; + cpuflpr_sram: memory@20028000 { + compatible = "mmio-sram"; + /* Size must be increased due to booting from SRAM */ + reg = <0x20028000 DT_SIZE_K(96)>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x20028000 0x18000>; + status = "okay"; + }; }; &cpuflpr_rram { diff --git a/boards/nordic/nrf54lm20dk/Kconfig b/boards/nordic/nrf54lm20dk/Kconfig new file mode 100644 index 000000000000..0b1905a0d8ef --- /dev/null +++ b/boards/nordic/nrf54lm20dk/Kconfig @@ -0,0 +1,28 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +DT_NRF_MPC := $(dt_nodelabel_path,nrf_mpc) + +if BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP_NS + +config NRF_TRUSTZONE_FLASH_REGION_SIZE + hex + default $(dt_node_int_prop_hex,$(DT_NRF_MPC),override-granularity) + help + This defines the flash region size from the TrustZone perspective. + It is used when configuring the TrustZone and when setting alignments + requirements for the partitions. + This abstraction allows us to configure TrustZone without depending + on peripheral-specific symbols. + +config NRF_TRUSTZONE_RAM_REGION_SIZE + hex + default $(dt_node_int_prop_hex,$(DT_NRF_MPC),override-granularity) + help + This defines the RAM region size from the TrustZone perspective. + It is used when configuring the TrustZone and when setting alignments + requirements for the partitions. + This abstraction allows us to configure TrustZone without depending + on peripheral specific symbols. + +endif # BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP_NS diff --git a/boards/nordic/nrf54lm20dk/Kconfig.defconfig b/boards/nordic/nrf54lm20dk/Kconfig.defconfig index 1f0a706ae6ca..c77e844b822c 100644 --- a/boards/nordic/nrf54lm20dk/Kconfig.defconfig +++ b/boards/nordic/nrf54lm20dk/Kconfig.defconfig @@ -6,7 +6,13 @@ if BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP config HW_STACK_PROTECTION default ARCH_HAS_STACK_PROTECTION -config ROM_START_OFFSET - default 0x800 if BOOTLOADER_MCUBOOT - endif # BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP + +if BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP_NS + +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y + +endif # BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP_NS diff --git a/boards/nordic/nrf54lm20dk/Kconfig.nrf54lm20dk b/boards/nordic/nrf54lm20dk/Kconfig.nrf54lm20dk index 83b3842211f3..b311fd9ae87e 100644 --- a/boards/nordic/nrf54lm20dk/Kconfig.nrf54lm20dk +++ b/boards/nordic/nrf54lm20dk/Kconfig.nrf54lm20dk @@ -2,5 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 config BOARD_NRF54LM20DK - select SOC_NRF54LM20A_ENGA_CPUAPP if BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP + select SOC_NRF54LM20A_ENGA_CPUAPP if BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP || BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP_NS select SOC_NRF54LM20A_ENGA_CPUFLPR if BOARD_NRF54LM20DK_NRF54LM20A_CPUFLPR diff --git a/boards/nordic/nrf54lm20dk/board.cmake b/boards/nordic/nrf54lm20dk/board.cmake index e487ecfb476f..6aaf6196d572 100644 --- a/boards/nordic/nrf54lm20dk/board.cmake +++ b/boards/nordic/nrf54lm20dk/board.cmake @@ -7,5 +7,13 @@ elseif(CONFIG_SOC_NRF54LM20A_ENGA_CPUFLPR) board_runner_args(jlink "--speed=4000") endif() +if(CONFIG_BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP_NS) + set(TFM_PUBLIC_KEY_FORMAT "full") +endif() + +if(CONFIG_TFM_FLASH_MERGED_BINARY) + set_property(TARGET runners_yaml_props_target PROPERTY hex_file tfm_merged.hex) +endif() + include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/nordic/nrf54lm20dk/board.yml b/boards/nordic/nrf54lm20dk/board.yml index 2930f9d3dfbd..86decbf7c7cd 100644 --- a/boards/nordic/nrf54lm20dk/board.yml +++ b/boards/nordic/nrf54lm20dk/board.yml @@ -5,6 +5,8 @@ board: socs: - name: nrf54lm20a variants: + - name: ns + cpucluster: cpuapp - name: xip cpucluster: cpuflpr runners: @@ -17,6 +19,7 @@ runners: groups: - boards: - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuflpr - nrf54lm20dk/nrf54lm20a/cpuflpr/xip '--erase': @@ -28,6 +31,7 @@ runners: groups: - boards: - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuflpr - nrf54lm20dk/nrf54lm20a/cpuflpr/xip '--reset': @@ -39,5 +43,6 @@ runners: groups: - boards: - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuflpr - nrf54lm20dk/nrf54lm20a/cpuflpr/xip diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20a_cpuapp_common.dtsi b/boards/nordic/nrf54lm20dk/nrf54lm20a_cpuapp_common.dtsi index d6184705899d..5b4599cc94e0 100644 --- a/boards/nordic/nrf54lm20dk/nrf54lm20a_cpuapp_common.dtsi +++ b/boards/nordic/nrf54lm20dk/nrf54lm20a_cpuapp_common.dtsi @@ -18,9 +18,13 @@ zephyr,bt-c2h-uart = &uart20; zephyr,flash-controller = &rram_controller; zephyr,flash = &cpuapp_rram; - zephyr,bt-hci = &bt_hci_controller; zephyr,ieee802154 = &ieee802154; }; + + aliases { + mcuboot-button0 = &button0; + mcuboot-led0 = &led0; + }; }; &cpuapp_sram { @@ -53,44 +57,6 @@ status = "okay"; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(449)>; - }; - - slot0_ns_partition: partition@80400 { - label = "image-0-nonsecure"; - reg = <0x80400 DT_SIZE_K(449)>; - }; - - slot1_partition: partition@f0800 { - label = "image-1"; - reg = <0xf0800 DT_SIZE_K(449)>; - }; - - slot1_ns_partition: partition@160c00 { - label = "image-1-nonsecure"; - reg = <0x160c00 DT_SIZE_K(449)>; - }; - - storage_partition: partition@1d1000 { - label = "storage"; - reg = <0x1d1000 DT_SIZE_K(36)>; - }; - }; -}; - &uart20 { status = "okay"; }; @@ -131,10 +97,6 @@ status = "okay"; }; -&bt_hci_controller { - status = "okay"; -}; - &ieee802154 { status = "okay"; }; diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.dts b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.dts index 6dd2c5b2e850..0496f3ca90cf 100644 --- a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.dts +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.dts @@ -7,6 +7,7 @@ /dts-v1/; #include "nrf54lm20a_cpuapp_common.dtsi" +#include / { compatible = "nordic,nrf54lm20dk_nrf54lm20a-cpuapp"; @@ -18,9 +19,5 @@ }; }; -&bt_hci_controller { - status = "okay"; -}; - /* Get a node label for wi-fi spi to use in shield files */ wifi_spi: &spi22 {}; diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_ns.dts b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_ns.dts new file mode 100644 index 000000000000..04cb9d04a60c --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_ns.dts @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#define USE_NON_SECURE_ADDRESS_MAP 1 + +#include "nrf54lm20a_cpuapp_common.dtsi" + +/ { + compatible = "nordic,nrf54lm20dk_nrf54lm20a-cpuapp-ns"; + model = "Nordic nRF54LM20 DK nRF54LM20A Application MCU Non-Secure"; + + chosen { + zephyr,code-partition = &slot0_ns_partition; + zephyr,sram = &sram0_ns; + zephyr,entropy = &psa_rng; + }; + + /delete-node/ rng; + + psa_rng: psa-rng { + status = "okay"; + }; +}; + +/ { + /* + * Default SRAM planning when building for nRF54LM20A with ARM TrustZone-M support + * - Lowest 208 kB SRAM allocated to Secure image (sram0_s). + * - Upper 208 kB SRAM allocated to Non-Secure image (sram0_ns). + * + * nRF54LM20A has 512 kB of volatile memory (SRAM), but 96kB is allocated for the FLPR MCU. + * This static layout needs to be the same with the upstream TF-M layout in the + * header flash_layout.h of the relevant platform. Any updates in the layout + * needs to happen both in the flash_layout.h and in this file at the same time. + */ + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram0_s: image_s@20000000 { + /* Secure image memory */ + reg = <0x20000000 DT_SIZE_K(208)>; + }; + + sram0_ns: image_ns@20034000 { + /* Non-Secure image memory */ + reg = <0x20034000 DT_SIZE_K(208)>; + }; + }; +}; + +&bt_hci_controller { + status = "disabled"; +}; + +&uart30 { + /* Disable so that TF-M can use this UART */ + status = "disabled"; +}; + +/* Include default memory partition configuration file */ +#include diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_ns.yaml b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_ns.yaml new file mode 100644 index 000000000000..3f10201892fb --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_ns.yaml @@ -0,0 +1,22 @@ +identifier: nrf54lm20dk/nrf54lm20a/cpuapp/ns +name: nRF54lm20-DK-nRF54lm20a-Application-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - zephyr +ram: 208 +flash: 1356 +supported: + - adc + - counter + - dmic + - gpio + - i2c + - i2s + - pwm + - spi + - usbd + - watchdog +vendor: nordic +sysbuild: true diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_ns_defconfig b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_ns_defconfig new file mode 100644 index 000000000000..d360ef89bac4 --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_ns_defconfig @@ -0,0 +1,45 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y +CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# Use devicetree code partition for TF-M +CONFIG_USE_DT_CODE_PARTITION=y + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable GPIO +CONFIG_GPIO=y + +# Don't enable the cache in the non-secure image as it is a +# secure-only peripheral on 54l +CONFIG_CACHE_MANAGEMENT=n +CONFIG_EXTERNAL_CACHE=n + +# Start SYSCOUNTER on driver init +CONFIG_NRF_GRTC_START_SYSCOUNTER=y + +# Disable TFM BL2 since it is not supported +CONFIG_TFM_BL2=n +# Support for silence logging is not supported at the moment +# Tracked by: NCSDK-31930 +CONFIG_TFM_LOG_LEVEL_SILENCE=n + +# The oscillators are configured as secure and cannot be configured +# from the non secure application directly. This needs to be set +# otherwise nrfx will try to configure them, resulting in a bus +# fault. +CONFIG_NRF_SKIP_CLOCK_CONFIG=y diff --git a/boards/nordic/nrf7002dk/CMakeLists.txt b/boards/nordic/nrf7002dk/CMakeLists.txt new file mode 100644 index 000000000000..db20255712bc --- /dev/null +++ b/boards/nordic/nrf7002dk/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if((CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NS OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS) AND + CONFIG_BOARD_ENABLE_CPUNET) + zephyr_library() + zephyr_library_sources(nrf5340_cpunet_reset.c) +endif() diff --git a/boards/nordic/nrf7002dk/Kconfig b/boards/nordic/nrf7002dk/Kconfig index fa6c8097ae32..d4b7030a65ab 100644 --- a/boards/nordic/nrf7002dk/Kconfig +++ b/boards/nordic/nrf7002dk/Kconfig @@ -10,7 +10,9 @@ config MBOX_NRFX_IPC default MBOX if BOARD_NRF7002DK_NRF5340_CPUAPP || \ - BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS config BT_HCI_IPC default y if BT diff --git a/boards/nordic/nrf7002dk/Kconfig.defconfig b/boards/nordic/nrf7002dk/Kconfig.defconfig index 48510d6e24f8..0d89a0089968 100644 --- a/boards/nordic/nrf7002dk/Kconfig.defconfig +++ b/boards/nordic/nrf7002dk/Kconfig.defconfig @@ -9,3 +9,75 @@ config HW_STACK_PROTECTION default ARCH_HAS_STACK_PROTECTION endif # BOARD_NRF7002DK + +if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +# By default, if we build for a Non-Secure version of the board, +# force building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + +# Code Partition: +# +# For the secure version of the board the firmware is linked at the beginning +# of the flash, or into the code-partition defined in DT if it is intended to +# be loaded by MCUboot. If the secure firmware is to be combined with a non- +# secure image (TRUSTED_EXECUTION_SECURE=y), the secure FW image shall always +# be restricted to the size of its code partition. +# +# For the non-secure version of the board, the firmware +# must be linked into the code-partition (non-secure) defined in DT, regardless. +# Apply this configuration below by setting the Kconfig symbols used by +# the linker according to the information extracted from DT partitions. + +# SRAM Partition: +# +# If the secure firmware is to be combined with a non-secure image +# (TRUSTED_EXECUTION_SECURE=y), the secure FW image SRAM shall always +# be restricted to the secure image SRAM partition (sram-secure-partition). +# Otherwise (if TRUSTED_EXECUTION_SECURE is not set) the whole zephyr,sram +# may be used by the image. +# +# For the non-secure version of the board, the firmware image SRAM is +# always restricted to the allocated non-secure SRAM partition. +# +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition +DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition + +if (BOARD_NRF7002DK_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001) && \ + TRUSTED_EXECUTION_SECURE + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config SRAM_SIZE + default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM_PARTITION),0,K) + +endif + +if BOARD_NRF7002DK_NRF5340_CPUAPP_NS || BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +config FLASH_LOAD_OFFSET + default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +endif + +endif diff --git a/boards/nordic/nrf7002dk/Kconfig.nrf7002dk b/boards/nordic/nrf7002dk/Kconfig.nrf7002dk index 61b9e818f367..91f52ee6f08c 100644 --- a/boards/nordic/nrf7002dk/Kconfig.nrf7002dk +++ b/boards/nordic/nrf7002dk/Kconfig.nrf7002dk @@ -4,4 +4,6 @@ config BOARD_NRF7002DK select SOC_NRF5340_CPUNET_QKAA if BOARD_NRF7002DK_NRF5340_CPUNET select SOC_NRF5340_CPUAPP_QKAA if BOARD_NRF7002DK_NRF5340_CPUAPP || \ - BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS diff --git a/boards/nordic/nrf7002dk/board.cmake b/boards/nordic/nrf7002dk/board.cmake index f85bbc86f485..11a27910eebc 100644 --- a/boards/nordic/nrf7002dk/board.cmake +++ b/boards/nordic/nrf7002dk/board.cmake @@ -1,10 +1,24 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -if(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP OR CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001) +if(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NS OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS) + set(TFM_PUBLIC_KEY_FORMAT "full") +endif() + +if(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NS OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS) board_runner_args(nrfutil "--ext-mem-config-file=${BOARD_DIR}/support/nrf7002dk_spi_nrfutil_config.json") board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") -elseif(CONFIG_BOARD_NRF7002DK_NRF5340_CPUNET) +endif() + +if(CONFIG_TFM_FLASH_MERGED_BINARY) + set_property(TARGET runners_yaml_props_target PROPERTY hex_file "${CMAKE_BINARY_DIR}/zephyr/tfm_merged.hex") +endif() + +if(CONFIG_BOARD_NRF7002DK_NRF5340_CPUNET) board_runner_args(jlink "--device=nrf5340_xxaa_net" "--speed=4000") endif() diff --git a/boards/nordic/nrf7002dk/board.yml b/boards/nordic/nrf7002dk/board.yml index 4f41341e4423..39db5dcfa3a7 100644 --- a/boards/nordic/nrf7002dk/board.yml +++ b/boards/nordic/nrf7002dk/board.yml @@ -5,5 +5,9 @@ board: socs: - name: nrf5340 variants: + - name: ns + cpucluster: cpuapp - name: nrf7001 cpucluster: cpuapp + variants: + - name: ns diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.dts b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.dts new file mode 100644 index 000000000000..5ff28accf3fc --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.dts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "nrf5340_cpuapp_common.dtsi" + +/ { + model = "Nordic NRF5340 DK NRF5340 Application"; + compatible = "nordic,nrf5340-dk-nrf5340-cpuapp"; + + chosen { + zephyr,sram = &sram0_ns; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_ns_partition; + zephyr,entropy = &psa_rng; + zephyr,wifi = &wlan0; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; +}; + +&qspi { + nrf70: nrf7001@1 { + compatible = "nordic,nrf7001-qspi"; + status = "okay"; + reg = <1>; + qspi-frequency = <24000000>; + qspi-quad-mode; + + #include "nrf70_common.dtsi" + }; +}; diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.yaml b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.yaml new file mode 100644 index 000000000000..165759691260 --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.yaml @@ -0,0 +1,19 @@ +identifier: nrf7002dk/nrf5340/cpuapp/nrf7001/ns +name: NRF7002-DK-NRF7001-NRF5340-application-MCU-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 192 +flash: 192 +supported: + - gpio + - i2c + - pwm + - watchdog + - usbd + - usb_device + - netif:openthread +vendor: nordic diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns_defconfig b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns_defconfig new file mode 100644 index 000000000000..2c435653140a --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns_defconfig @@ -0,0 +1,24 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.dts b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.dts new file mode 100644 index 000000000000..9c06a17ad7bf --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.dts @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "nrf5340_cpuapp_common.dtsi" +#include "nordic/nrf5340_sram_partition.dtsi" +#include "nordic/nrf5340_cpuapp_ns_partition.dtsi" + +/ { + model = "Nordic NRF5340 DK NRF5340 Application"; + compatible = "nordic,nrf5340-dk-nrf5340-cpuapp"; + + chosen { + zephyr,sram = &sram0_ns_app; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_ns_partition; + zephyr,entropy = &psa_rng; + zephyr,wifi = &wlan0; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; +}; + +&qspi { + nrf70: nrf7002@1 { + compatible = "nordic,nrf7002-qspi"; + status = "okay"; + reg = <1>; + qspi-frequency = <24000000>; + qspi-quad-mode; + + #include "nrf70_common.dtsi" + #include "nrf70_common_5g.dtsi" + }; +}; diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.yaml b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.yaml new file mode 100644 index 000000000000..ea43785b4559 --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.yaml @@ -0,0 +1,19 @@ +identifier: nrf7002dk/nrf5340/cpuapp/ns +name: NRF7002-DK-NRF5340-application-MCU-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 192 +flash: 192 +supported: + - gpio + - i2c + - pwm + - watchdog + - usbd + - usb_device + - netif:openthread +vendor: nordic diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns_defconfig b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns_defconfig new file mode 100644 index 000000000000..1886b926bfd5 --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns_defconfig @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/nordic/nrf9131ek/Kconfig.defconfig b/boards/nordic/nrf9131ek/Kconfig.defconfig index e1d8de241c0a..1a30d006b4c6 100644 --- a/boards/nordic/nrf9131ek/Kconfig.defconfig +++ b/boards/nordic/nrf9131ek/Kconfig.defconfig @@ -8,3 +8,22 @@ config HW_STACK_PROTECTION config BOARD_NRF9131EK select USE_DT_CODE_PARTITION if BOARD_NRF9131EK_NRF9131_NS + +if BOARD_NRF9131EK_NRF9131 || BOARD_NRF9131EK_NRF9131_NS + +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_NRF9131EK_NRF9131_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + +endif # BOARD_NRF9131EK_NRF9131 || BOARD_NRF9131EK_NRF9131_NS diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map.dtsi b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map.dtsi index 0127998509e8..67c70f1d38b5 100644 --- a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map.dtsi +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map.dtsi @@ -221,4 +221,14 @@ reg = <0x680000 DT_SIZE_K(24)>; }; }; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + periphconf_partition: partition@60a000 { + reg = <0x60a000 DT_SIZE_K(8)>; + }; + }; }; diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map_iron.dtsi b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map_iron.dtsi index aa95021d887c..fba2e0fb6c2d 100644 --- a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map_iron.dtsi +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map_iron.dtsi @@ -16,16 +16,19 @@ / { reserved-memory { - cpuapp_cpusys_ipc_shm: memory@2f88f600 { - reg = <0x2f88f600 0x80>; + /* Workaround for a data cache related issue with SoC1.1, use secure addresses + * for cpuapp_cpusys_ipc_shm, cpusys_cpuapp_ipc_shm and cpusec_cpuapp_ipc_shm. + */ + cpuapp_cpusys_ipc_shm: memory@3f88f600 { + reg = <0x3f88f600 0x80>; }; - cpusys_cpuapp_ipc_shm: memory@2f88f680 { - reg = <0x2f88f680 0x80>; + cpusys_cpuapp_ipc_shm: memory@3f88f680 { + reg = <0x3f88f680 0x80>; }; - cpusec_cpuapp_ipc_shm: memory@2f88fb80 { - reg = <0x2f88fb80 0x80>; + cpusec_cpuapp_ipc_shm: memory@3f88fb80 { + reg = <0x3f88fb80 0x80>; }; cpuapp_ironside_se_event_report: memory@2f88fc00 { @@ -75,5 +78,28 @@ storage_partition: partition@600000 { reg = <0x600000 DT_SIZE_K(40)>; }; + + periphconf_partition: partition@60a000 { + reg = <0x60a000 DT_SIZE_K(8)>; + }; + + /* 0x60c000 was chosen for secure_storage_partition such that + * it resides in the beginning of MRAM11 in storage partition. + */ + secure_storage_partition: partition@60c000 { + compatible = "fixed-subpartitions"; + reg = <0x60c000 DT_SIZE_K(8)>; + ranges = <0x0 0x60c000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_crypto_partition: partition@0 { + reg = <0x0 DT_SIZE_K(4)>; + }; + + cpuapp_its_partition: partition@1000 { + reg = <0x1000 DT_SIZE_K(4)>; + }; + }; }; }; diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts index 622fc04e96af..19dd5e208063 100644 --- a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts @@ -26,6 +26,7 @@ zephyr,shell-uart = &uart136; zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; + zephyr,entropy = &psa_rng; }; aliases { @@ -107,6 +108,11 @@ pwms = <&pwm130 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; }; }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; }; &cpuapp_ram0x_region { diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron_0_2_0.overlay b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron_0_2_0.overlay new file mode 100644 index 000000000000..4fa3f667eadd --- /dev/null +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron_0_2_0.overlay @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf9280pdk_nrf9280-pinctrl_0_2_0.dtsi" + +/ { + aliases { + pwm-led0 = &pwm_led2; /* Alias for compatibility with samples that use pwm-led0 */ + }; + + leds { + compatible = "gpio-leds"; + + led0: led_0 { + gpios = <&gpio9 0 GPIO_ACTIVE_HIGH>; + label = "Green LED 0"; + }; + + led1: led_1 { + gpios = <&gpio9 1 GPIO_ACTIVE_HIGH>; + label = "Green LED 1"; + }; + + led2: led_2 { + gpios = <&gpio9 2 GPIO_ACTIVE_HIGH>; + label = "Green LED 2"; + }; + + led3: led_3 { + gpios = <&gpio9 3 GPIO_ACTIVE_HIGH>; + label = "Green LED 3"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + + /delete-node/ pwm_led_0; + + /* + * There is no valid hardware configuration to pass PWM signal on pins 0 and 1. + * First valid config is P9.2. This corresponds to LED 2. + * Signal on PWM130's channel 0 can be passed directly on GPIO Port 9 pin 2. + */ + pwm_led2: pwm_led_2 { + pwms = <&pwm130 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; +}; diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuppr_xip_0_2_0.overlay b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuppr_xip_0_2_0.overlay new file mode 100644 index 000000000000..f2d986e6cb06 --- /dev/null +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuppr_xip_0_2_0.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf9280pdk_nrf9280-pinctrl_0_2_0.dtsi" diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad.dts b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad.dts index 5efa7dbd471c..91d967ea34aa 100644 --- a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad.dts +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad.dts @@ -28,12 +28,18 @@ zephyr,ieee802154 = &cpurad_ieee802154; zephyr,bt-hci-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; + zephyr,entropy = &psa_rng; }; aliases { ipc-to-cpusys = &cpurad_cpusys_ipc; resetinfo = &cpurad_resetinfo; }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; }; &cpuapp_cpurad_ram0x_region { diff --git a/boards/nordic/thingy53/Kconfig.defconfig b/boards/nordic/thingy53/Kconfig.defconfig index c1139f0dca10..b7f33e89bf1b 100644 --- a/boards/nordic/thingy53/Kconfig.defconfig +++ b/boards/nordic/thingy53/Kconfig.defconfig @@ -8,6 +8,12 @@ config HW_STACK_PROTECTION if BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS +config BOOTLOADER_MCUBOOT + default y if !MCUBOOT + +config BOARD_ENABLE_CPUNET + default y if !MCUBOOT + # Code Partition: # # For the secure version of the board the firmware is linked at the beginning @@ -84,6 +90,16 @@ endif # !TRUSTED_EXECUTION_SECURE source "boards/common/usb/Kconfig.cdc_acm_serial.defconfig" +# By default, a USB CDC ACM instance is already enabled in the board's DTS. +# It is not necessary for nRF Connect SDK to add another instance if MCUBoot +# bootloader is built as a child image. +config MCUBOOT_USB_SUPPORT + bool + default n + +config NORDIC_QSPI_NOR + default y + endif # BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS if BOARD_THINGY53_NRF5340_CPUNET diff --git a/boards/nordic/thingy53/Kconfig.sysbuild b/boards/nordic/thingy53/Kconfig.sysbuild new file mode 100644 index 000000000000..df489c1dd546 --- /dev/null +++ b/boards/nordic/thingy53/Kconfig.sysbuild @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y if SECURE_BOOT_NETCORE + +config NRF_DEFAULT_EMPTY + default y if SECURE_BOOT_NETCORE + +config MCUBOOT_USE_ALL_AVAILABLE_RAM + default y if BOARD_THINGY53_NRF5340_CPUAPP_NS && BOOTLOADER_MCUBOOT + +endif # BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y if BOOTLOADER_MCUBOOT diff --git a/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp.yml b/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp.yml new file mode 100644 index 000000000000..7a48d51ec334 --- /dev/null +++ b/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp.yml @@ -0,0 +1,55 @@ +app: + address: 0x10200 + region: flash_primary + size: 0xdfe00 +mcuboot: + address: 0x0 + region: flash_primary + size: 0x10000 +mcuboot_pad: + address: 0x10000 + region: flash_primary + size: 0x200 +mcuboot_primary: + address: 0x10000 + orig_span: &id001 + - mcuboot_pad + - app + region: flash_primary + size: 0xe0000 + span: *id001 +mcuboot_primary_app: + address: 0x10200 + orig_span: &id002 + - app + region: flash_primary + size: 0xdfe00 + span: *id002 +settings_storage: + address: 0xf0000 + region: flash_primary + size: 0x10000 +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x00000 + size: 0xe0000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xe0000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x120000 + size: 0x6e0000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp_ns.yml b/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp_ns.yml new file mode 100644 index 000000000000..70ffe6d9c124 --- /dev/null +++ b/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp_ns.yml @@ -0,0 +1,73 @@ +mcuboot: + address: 0x0 + region: flash_primary + size: 0x10000 +mcuboot_pad: + address: 0x10000 + region: flash_primary + size: 0x200 +tfm_secure: + address: 0x10000 + size: 0xc000 + span: [mcuboot_pad, tfm] +tfm_nonsecure: + address: 0x1c000 + size: 0xd4000 + span: [app] +tfm: + address: 0x10200 + region: flash_primary + size: 0xbe00 +app: + address: 0x1c000 + region: flash_primary + size: 0xd4000 +mcuboot_primary: + address: 0x10000 + orig_span: &id001 + - mcuboot_pad + - tfm + - app + region: flash_primary + size: 0xe0000 + span: *id001 +mcuboot_primary_app: + address: 0x10200 + orig_span: &id002 + - tfm + - app + region: flash_primary + size: 0xdfe00 + span: *id002 +nonsecure_storage: + address: 0xf0000 + size: 0x10000 + span: [settings_storage] +settings_storage: + address: 0xf0000 + region: flash_primary + size: 0x10000 +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x00000 + size: 0xe0000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xe0000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x120000 + size: 0x6e0000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi b/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi index fabd5d177a99..c8042b284755 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi +++ b/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi @@ -13,6 +13,7 @@ zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; + nordic,pm-ext-flash = &mx25r64; }; buttons { diff --git a/boards/panasonic/panb611evb/Kconfig.defconfig b/boards/panasonic/panb611evb/Kconfig.defconfig index 6ad6d9426dbf..1b469232537f 100644 --- a/boards/panasonic/panb611evb/Kconfig.defconfig +++ b/boards/panasonic/panb611evb/Kconfig.defconfig @@ -5,13 +5,6 @@ DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition -if BOARD_PANB611EVB_NRF54L15_CPUAPP - -config ROM_START_OFFSET - default 0x800 if BOOTLOADER_MCUBOOT - -endif # BOARD_PANB611EVB_NRF54L15_CPUAPP - if BOARD_PANB611EVB_NRF54L15_CPUAPP_NS config HAS_BT_CTLR diff --git a/boards/panasonic/panb611evb/panb611evb_nrf54l15_cpuapp_ns_defconfig b/boards/panasonic/panb611evb/panb611evb_nrf54l15_cpuapp_ns_defconfig index 5f6e098f4528..e360981191e8 100644 --- a/boards/panasonic/panb611evb/panb611evb_nrf54l15_cpuapp_ns_defconfig +++ b/boards/panasonic/panb611evb/panb611evb_nrf54l15_cpuapp_ns_defconfig @@ -33,4 +33,4 @@ CONFIG_TFM_LOG_LEVEL_SILENCE=n # from the non secure application directly. This needs to be set # otherwise nrfx will try to configure them, resulting in a bus # fault. -CONFIG_SOC_NRF54LX_SKIP_CLOCK_CONFIG=y +CONFIG_NRF_SKIP_CLOCK_CONFIG=y diff --git a/boards/raytac/an54l15q_db/Kconfig.defconfig b/boards/raytac/an54l15q_db/Kconfig.defconfig index 72616407eb7b..0d903ea091d0 100644 --- a/boards/raytac/an54l15q_db/Kconfig.defconfig +++ b/boards/raytac/an54l15q_db/Kconfig.defconfig @@ -6,13 +6,6 @@ DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition -if BOARD_RAYTAC_AN54L15Q_DB_NRF54L15_CPUAPP - -config ROM_START_OFFSET - default 0x800 if BOOTLOADER_MCUBOOT - -endif # BOARD_RAYTAC_AN54L15Q_DB_NRF54L15_CPUAPP - if BOARD_RAYTAC_AN54L15Q_DB_NRF54L15_CPUAPP_NS config HAS_BT_CTLR diff --git a/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp_ns_defconfig b/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp_ns_defconfig index 866a03cd8687..0df2316b4502 100644 --- a/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp_ns_defconfig +++ b/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp_ns_defconfig @@ -34,4 +34,4 @@ CONFIG_TFM_LOG_LEVEL_SILENCE=n # from the non secure application directly. This needs to be set # otherwise nrfx will try to configure them, resulting in a bus # fault. -CONFIG_SOC_NRF54LX_SKIP_CLOCK_CONFIG=y +CONFIG_NRF_SKIP_CLOCK_CONFIG=y diff --git a/boards/seeed/xiao_ble/pm_static.yml b/boards/seeed/xiao_ble/pm_static.yml new file mode 100644 index 000000000000..02915293177c --- /dev/null +++ b/boards/seeed/xiao_ble/pm_static.yml @@ -0,0 +1,18 @@ +# Mirror of partitions defined in nrf52840_partition_uf2_sdv7.dtsi +# Default flash layout for nrf52840 using UF2 and SoftDevice s140 v7 + +softdevice_reserved: + address: 0x00 + size: 0x27000 + +app: + address: 0x27000 + size: 0xC5000 + +settings_storage: + address: 0xEC000 + size: 0x8000 + +uf2_partition: + address: 0xF4000 + size: 0xC000 diff --git a/boards/seeed/xiao_nrf54l15/Kconfig.defconfig b/boards/seeed/xiao_nrf54l15/Kconfig.defconfig index dd9a6feb90e6..9dae62ca0403 100644 --- a/boards/seeed/xiao_nrf54l15/Kconfig.defconfig +++ b/boards/seeed/xiao_nrf54l15/Kconfig.defconfig @@ -5,7 +5,4 @@ if BOARD_XIAO_NRF54L15_NRF54L15_CPUAPP config HAS_BT_CTLR default BT -config ROM_START_OFFSET - default 0x800 if BOOTLOADER_MCUBOOT - endif # BOARD_XIAO_NRF54L15_NRF54L15_CPUAPP diff --git a/boards/we/ophelia4ev/Kconfig.defconfig b/boards/we/ophelia4ev/Kconfig.defconfig index ae367b374d7e..2c11dd05e163 100644 --- a/boards/we/ophelia4ev/Kconfig.defconfig +++ b/boards/we/ophelia4ev/Kconfig.defconfig @@ -1,9 +1,5 @@ # Copyright (c) 2025 Würth Elektronik eiSos GmbH & Co. KG # SPDX-License-Identifier: Apache-2.0 -if BOARD_OPHELIA4EV_NRF54L15_CPUAPP - -config ROM_START_OFFSET - default 0x800 if BOOTLOADER_MCUBOOT - -endif # BOARD_OPHELIA4EV_NRF54L15_CPUAPP +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION diff --git a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.dts b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.dts index 2380fcd5b8d3..9acc3e1fff90 100644 --- a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.dts +++ b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.dts @@ -15,14 +15,20 @@ chosen { zephyr,console = &uart20; zephyr,shell-uart = &uart20; - zephyr,code-partition = &slot0_partition; - zephyr,flash = &cpuapp_rram; - zephyr,sram = &cpuapp_sram; zephyr,uart-mcumgr = &uart20; zephyr,bt-mon-uart = &uart20; zephyr,bt-c2h-uart = &uart20; zephyr,flash-controller = &rram_controller; + zephyr,flash = &cpuapp_rram; zephyr,ieee802154 = &ieee802154; + zephyr,boot-mode = &boot_mode0; + zephyr,code-partition = &slot0_partition; + zephyr,sram = &cpuapp_sram; + }; + + aliases { + mcuboot-button0 = &button0; + mcuboot-led0 = &led0; }; }; @@ -32,7 +38,7 @@ &lfxo { load-capacitors = "internal"; - load-capacitance-femtofarad = <15500>; + load-capacitance-femtofarad = <17000>; }; &hfxo { @@ -63,6 +69,10 @@ status = "okay"; }; +&nfct { + status = "okay"; +}; + &gpio0 { status = "okay"; }; @@ -99,6 +109,16 @@ status = "okay"; }; +&gpregret1 { + status = "okay"; + + boot_mode0: boot_mode@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x1>; + }; +}; + &spi00 { status = "okay"; @@ -126,6 +146,7 @@ has-dpd; t-enter-dpd = <10000>; t-exit-dpd = <35000>; + reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>; }; }; diff --git a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp_defconfig b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp_defconfig index 80a40b5a79d9..f880aa57105c 100644 --- a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp_defconfig +++ b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp_defconfig @@ -14,8 +14,5 @@ CONFIG_GPIO=y # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Use internal LFCLK CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y diff --git a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuflpr.yaml b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuflpr.yaml index a302cf4a192d..6e1264242d64 100644 --- a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuflpr.yaml +++ b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuflpr.yaml @@ -15,4 +15,3 @@ supported: - gpio - i2c - spi - - watchdog diff --git a/cmake/linker/arcmwdt/linker_flags.cmake b/cmake/linker/arcmwdt/linker_flags.cmake index 32c6cb9dd660..e2984268d9db 100644 --- a/cmake/linker/arcmwdt/linker_flags.cmake +++ b/cmake/linker/arcmwdt/linker_flags.cmake @@ -41,6 +41,8 @@ check_set_linker_property(TARGET linker PROPERTY orphan_error ${LINKERFLAGPREFIX},--orphan-handling=error ) +check_set_linker_property(TARGET linker PROPERTY undefined ${LINKERFLAGPREFIX},-u) + set_property(TARGET linker PROPERTY partial_linking "-r") # Extra warnings options for twister run diff --git a/cmake/linker/armlink/linker_flags.cmake b/cmake/linker/armlink/linker_flags.cmake new file mode 100644 index 000000000000..207f83246a8f --- /dev/null +++ b/cmake/linker/armlink/linker_flags.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2025 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 + +set_property(TARGET linker PROPERTY undefined --undefined=) diff --git a/cmake/linker/iar/linker_flags.cmake b/cmake/linker/iar/linker_flags.cmake index 12d44ca24cd2..cdfc3a8e9a5a 100644 --- a/cmake/linker/iar/linker_flags.cmake +++ b/cmake/linker/iar/linker_flags.cmake @@ -23,6 +23,7 @@ set_property(TARGET linker PROPERTY optimization_speed --entry_list_in_address_o set_property(TARGET linker PROPERTY optimization_size --entry_list_in_address_order) set_property(TARGET linker PROPERTY optimization_size_aggressive --entry_list_in_address_order) +set_linker_property(TARGET linker PROPERTY undefined "--keep=") string(APPEND CMAKE_C_LINK_FLAGS --no-wrap-diagnostics) diff --git a/cmake/linker/ld/linker_flags.cmake b/cmake/linker/ld/linker_flags.cmake index 885a1844cc5d..33e5cd59322d 100644 --- a/cmake/linker/ld/linker_flags.cmake +++ b/cmake/linker/ld/linker_flags.cmake @@ -22,6 +22,8 @@ check_set_linker_property(TARGET linker PROPERTY orphan_error ${LINKERFLAGPREFIX},--orphan-handling=error ) +set_property(TARGET linker PROPERTY undefined ${LINKERFLAGPREFIX},--undefined=) + check_set_linker_property(TARGET linker PROPERTY memusage "${LINKERFLAGPREFIX},--print-memory-usage") check_set_linker_property(TARGET linker PROPERTY sanitizer_undefined -fsanitize=undefined) diff --git a/cmake/linker/ld/target.cmake b/cmake/linker/ld/target.cmake index 592596576d11..ccf6a1903162 100644 --- a/cmake/linker/ld/target.cmake +++ b/cmake/linker/ld/target.cmake @@ -80,6 +80,7 @@ macro(configure_linker_script linker_script_gen linker_pass_define) ${current_includes} ${soc_linker_script_includes} ${template_script_defines} + -DUSE_PARTITION_MANAGER=$ -E ${LINKER_SCRIPT} -P # Prevent generation of debug `#line' directives. -o ${linker_script_gen} diff --git a/cmake/linker/lld/target.cmake b/cmake/linker/lld/target.cmake index 96df1c123796..fe8aad62c73d 100644 --- a/cmake/linker/lld/target.cmake +++ b/cmake/linker/lld/target.cmake @@ -52,6 +52,7 @@ macro(configure_linker_script linker_script_gen linker_pass_define) -imacros ${AUTOCONF_H} ${current_includes} ${template_script_defines} + -DUSE_PARTITION_MANAGER=$ -E ${LINKER_SCRIPT} -P # Prevent generation of debug `#line' directives. -o ${linker_script_gen} diff --git a/cmake/linker/xt-ld/linker_flags.cmake b/cmake/linker/xt-ld/linker_flags.cmake index ab66461e4522..535d76ecf650 100644 --- a/cmake/linker/xt-ld/linker_flags.cmake +++ b/cmake/linker/xt-ld/linker_flags.cmake @@ -19,11 +19,11 @@ check_set_linker_property(TARGET linker PROPERTY baremetal ) check_set_linker_property(TARGET linker PROPERTY orphan_warning - ${LINKERFLAGPREFIX},--orphan-handling=warn + ${LINKERFLAGPREFIX},--orphan-handling=warn ) check_set_linker_property(TARGET linker PROPERTY orphan_error - ${LINKERFLAGPREFIX},--orphan-handling=error + ${LINKERFLAGPREFIX},--orphan-handling=error ) set_property(TARGET linker PROPERTY partial_linking "-r") @@ -34,3 +34,5 @@ check_set_linker_property(TARGET linker PROPERTY sort_alignment ${LINKERFLAGPREFIX},--sort-common=descending ${LINKERFLAGPREFIX},--sort-section=alignment ) + +set_property(TARGET linker PROPERTY undefined ${LINKERFLAGPREFIX},--undefined=) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 55ce61fffc6a..5aacb8690da0 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -4705,6 +4705,7 @@ function(zephyr_dt_import) zephyr_check_arguments_required_all(${CMAKE_CURRENT_FUNCTION} arg ${req_single_args}) set(gen_dts_cmake_script ${ZEPHYR_BASE}/scripts/dts/gen_dts_cmake.py) + set(gen_dts_cmake_temp ${arg_EDT_PICKLE_FILE}.cmake.new) set(gen_dts_cmake_output ${arg_EDT_PICKLE_FILE}.cmake) if((${arg_EDT_PICKLE_FILE} IS_NEWER_THAN ${gen_dts_cmake_output}) OR @@ -4713,11 +4714,13 @@ function(zephyr_dt_import) execute_process( COMMAND ${PYTHON_EXECUTABLE} ${gen_dts_cmake_script} --edt-pickle ${arg_EDT_PICKLE_FILE} - --cmake-out ${gen_dts_cmake_output} + --cmake-out ${gen_dts_cmake_temp} WORKING_DIRECTORY ${PROJECT_BINARY_DIR} RESULT_VARIABLE ret COMMAND_ERROR_IS_FATAL ANY ) + + file(COPY_FILE ${gen_dts_cmake_temp} ${gen_dts_cmake_output} ONLY_IF_DIFFERENT) endif() set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${gen_dts_cmake_script}) diff --git a/cmake/modules/kconfig.cmake b/cmake/modules/kconfig.cmake index de87abfdc1d3..60667eb6444b 100644 --- a/cmake/modules/kconfig.cmake +++ b/cmake/modules/kconfig.cmake @@ -132,10 +132,13 @@ endif() # APP_DIR: Path to the main image (sysbuild) or synonym for APPLICATION_SOURCE_DIR (non-sysbuild) zephyr_get(APP_DIR VAR APP_DIR APPLICATION_SOURCE_DIR) +# Load the module Kconfig file into CMake +include("${KCONFIG_BINARY_DIR}/kconfig_module_dirs.cmake") + set(COMMON_KCONFIG_ENV_SETTINGS PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} - KCONFIG_ENV_FILE=${KCONFIG_BINARY_DIR}/kconfig_module_dirs.env srctree=${ZEPHYR_BASE} + ${kconfig_env_dirs} KERNELVERSION=${KERNELVERSION} APPVERSION=${APP_VERSION_STRING} APP_VERSION_EXTENDED_STRING=${APP_VERSION_EXTENDED_STRING} diff --git a/cmake/modules/kernel.cmake b/cmake/modules/kernel.cmake index c6319611c8c3..5c8fa184b208 100644 --- a/cmake/modules/kernel.cmake +++ b/cmake/modules/kernel.cmake @@ -256,3 +256,7 @@ if("${CMAKE_EXTRA_GENERATOR}" STREQUAL "Eclipse CDT4") include(${ZEPHYR_BASE}/cmake/ide/eclipse_cdt4_generator_amendment.cmake) eclipse_cdt4_generator_amendment(1) endif() + +if(ZEPHYR_NRF_MODULE_DIR) + include(${ZEPHYR_NRF_MODULE_DIR}/cmake/partition_manager.cmake) +endif() diff --git a/doc/_extensions/zephyr/kconfig/__init__.py b/doc/_extensions/zephyr/kconfig/__init__.py index cda7430d7ab8..63459a61ade6 100644 --- a/doc/_extensions/zephyr/kconfig/__init__.py +++ b/doc/_extensions/zephyr/kconfig/__init__.py @@ -44,6 +44,7 @@ from typing import Any from docutils import nodes +from dotenv import load_dotenv from sphinx.addnodes import pending_xref from sphinx.application import Sphinx from sphinx.builders import Builder @@ -81,7 +82,8 @@ def kconfig_load(app: Sphinx) -> tuple[kconfiglib.Kconfig, kconfiglib.Kconfig, d sysbuild_kconfig = "" for module in modules: kconfig_module_dirs += zephyr_module.process_kconfig_module_dir(module.project, - module.meta) + module.meta, + False) kconfig += zephyr_module.process_kconfig(module.project, module.meta) sysbuild_kconfig += zephyr_module.process_sysbuildkconfig(module.project, module.meta) @@ -112,6 +114,9 @@ def kconfig_load(app: Sphinx) -> tuple[kconfiglib.Kconfig, kconfiglib.Kconfig, d for folder in soc_folders: f.write('source "' + (Path(folder) / 'Kconfig.soc').as_posix() + '"\n') + if "nordic" in folder: + f.write('osource "' + (Path(folder) / 'Kconfig.sysbuild').as_posix() + '"\n') + with open(Path(td) / "soc" / "Kconfig", "w") as f: for folder in soc_folders: f.write('osource "' + (Path(folder) / 'Kconfig').as_posix() + '"\n') @@ -155,7 +160,7 @@ def kconfig_load(app: Sphinx) -> tuple[kconfiglib.Kconfig, kconfiglib.Kconfig, d os.environ["BOARD"] = "boards" os.environ["KCONFIG_BOARD_DIR"] = str(Path(td) / "boards") - os.environ["KCONFIG_ENV_FILE"] = str(Path(td) / "kconfig_module_dirs.env") + load_dotenv(str(Path(td) / "kconfig_module_dirs.env")) # Sysbuild runs first os.environ["CONFIG_"] = "SB_CONFIG_" diff --git a/doc/build/kconfig/setting.rst b/doc/build/kconfig/setting.rst index ad62d86eb3d4..6fe1feaed7d3 100644 --- a/doc/build/kconfig/setting.rst +++ b/doc/build/kconfig/setting.rst @@ -7,8 +7,7 @@ The :ref:`menuconfig and guiconfig interfaces ` can be used to test out configurations during application development. This page explains how to make settings permanent. -All Kconfig options can be searched in the :ref:`Kconfig search page -`. +All Kconfig options can be searched in the Kconfig search page. .. note:: @@ -115,8 +114,7 @@ Assignments in configuration files are only respected if the dependencies for the symbol are satisfied. A warning is printed otherwise. To figure out what the dependencies of a symbol are, use one of the :ref:`interactive configuration interfaces ` (you can jump directly to a symbol with -:kbd:`/`), or look up the symbol in the :ref:`Kconfig search page -`. +:kbd:`/`), or look up the symbol in the Kconfig search page. .. _initial-conf: diff --git a/doc/connectivity/bluetooth/api/hci.txt b/doc/connectivity/bluetooth/api/hci.txt index 2ad17bfae5eb..a23b24e6ad0e 100644 --- a/doc/connectivity/bluetooth/api/hci.txt +++ b/doc/connectivity/bluetooth/api/hci.txt @@ -1085,14 +1085,13 @@ represents. | Event | Event Code | Event Parameters | +-------------------------------+------------+-------------------------------+ | Fatal_Error | 0xFF | Subevent_Code, | -| | | Error_Data_Type, | | | | Error_Data | +-------------------------------+------------+-------------------------------+ -The Error_Data_Type provides an information about what is the Error_Data size -and content. +The Subevent_Code provides an information about what is the Error_Data size and +content. - Error_Data_Type: Size: 1 Octet + Subevent_Code: Size: 1 Octet +--------------------+--------------------------------------+ | Value | Parameter Description | +--------------------+--------------------------------------+ @@ -1157,6 +1156,7 @@ Zephyr Fatal Error event may be generated by k_sys_fatal_error_handler. | a4 | 4 octets | General purpose register | | ip | 4 octets | Instruction pointer register | | lr | 4 octets | Link register | + | pc | 4 octets | Program counter register | | xpsr | 4 octets | Program status register | +--------------------+--------------------------------------------+ diff --git a/doc/connectivity/bluetooth/api/l2cap.rst b/doc/connectivity/bluetooth/api/l2cap.rst index 581edda83485..157f9684be13 100644 --- a/doc/connectivity/bluetooth/api/l2cap.rst +++ b/doc/connectivity/bluetooth/api/l2cap.rst @@ -3,11 +3,45 @@ Logical Link Control and Adaptation Protocol (L2CAP) #################################################### -L2CAP layer enables connection-oriented channels which can be enable with the -configuration option: :kconfig:option:`CONFIG_BT_L2CAP_DYNAMIC_CHANNEL`. This channels +L2CAP layer enables connection-oriented channels which can be enabled with the +configuration option: :kconfig:option:`CONFIG_BT_L2CAP_DYNAMIC_CHANNEL`. These channels support segmentation and reassembly transparently, they also support credit based flow control making it suitable for data streams. +The user can also define fixed channels using the :c:macro:`BT_L2CAP_FIXED_CHANNEL_DEFINE` +macro. Fixed channels are initialized upon connection, and do not support segmentation. An example +of how to define a fixed channel is shown below. + +.. code-block:: c + + static struct bt_l2cap_chan fixed_chan[CONFIG_BT_MAX_CONN]; + + /* Callbacks are assumed to be defined prior. */ + static struct bt_l2cap_chan_ops ops = { + .recv = recv_cb, + .sent = sent_cb, + .connected = connected_cb, + .disconnected = disconnected_cb, + }; + + static int l2cap_fixed_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) + { + uint8_t conn_index = bt_conn_index(conn); + + *chan = &fixed_chan[conn_index]; + + **chan = (struct bt_l2cap_chan){ + .ops = &ops, + }; + + return 0; + } + + BT_L2CAP_FIXED_CHANNEL_DEFINE(fixed_channel) = { + .cid = 0x0010, + .accept = l2cap_fixed_accept, + }; + Channels instances are represented by the :c:struct:`bt_l2cap_chan` struct which contains the callbacks in the :c:struct:`bt_l2cap_chan_ops` struct to inform when the channel has been connected, disconnected or when the encryption has diff --git a/doc/connectivity/bluetooth/api/mesh/provisioning.rst b/doc/connectivity/bluetooth/api/mesh/provisioning.rst index 685c9dda455a..311904882078 100644 --- a/doc/connectivity/bluetooth/api/mesh/provisioning.rst +++ b/doc/connectivity/bluetooth/api/mesh/provisioning.rst @@ -144,7 +144,7 @@ sequence should be repeated after a delay of three seconds or more. When an Input OOB action is selected, the user should be prompted when the application receives the :c:member:`bt_mesh_prov.input` callback. The user response should be fed back to the Provisioning API through -:c:func:`bt_mesh_input_string` or :c:func:`bt_mesh_input_number`. If +:c:func:`bt_mesh_input_string` or :c:func:`bt_mesh_input_numeric`. If no user response is recorded within 60 seconds, the Provisioning process is aborted. diff --git a/doc/connectivity/networking/api/mqtt.rst b/doc/connectivity/networking/api/mqtt.rst index 2775d77315b8..c2fb612e1cc2 100644 --- a/doc/connectivity/networking/api/mqtt.rst +++ b/doc/connectivity/networking/api/mqtt.rst @@ -150,6 +150,7 @@ additional configuration information: tls_config->sec_tag_list = m_sec_tags; tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags); tls_config->hostname = MQTT_BROKER_HOSTNAME; + tls_config->set_native_tls = true; In this sample code, the ``m_sec_tags`` array holds a list of tags, referencing TLS credentials that the MQTT library should use for authentication. We do not specify @@ -162,6 +163,8 @@ Note, that TLS credentials referenced by the ``m_sec_tags`` array must be registered in the system first. For more information on how to do that, refer to :ref:`secure sockets documentation `. +Finally, ``set_native_tls`` can be optionally set to enable native TLS support instead of offloading TLS operations to the modem. + An example of how to use TLS with MQTT is also present in :zephyr:code-sample:`mqtt-publisher` sample application. diff --git a/doc/develop/application/index.rst b/doc/develop/application/index.rst index c28fa011f3cc..4f8b5f868a56 100644 --- a/doc/develop/application/index.rst +++ b/doc/develop/application/index.rst @@ -649,9 +649,8 @@ started. See :ref:`setting_configuration_values` for detailed documentation on setting Kconfig configuration values. The :ref:`initial-conf` section on the same page -explains how the initial configuration is derived. See :ref:`kconfig-search` -for a complete list of configuration options. -See :ref:`hardening` for security information related with Kconfig options. +explains how the initial configuration is derived. See :ref:`hardening` for +security information related with Kconfig options. The other pages in the :ref:`Kconfig section of the manual ` are also worth going through, especially if you planning to add new configuration diff --git a/doc/hardware/peripherals/mspi.rst b/doc/hardware/peripherals/mspi.rst index 176c9bf5ede3..b9139f1ed1a8 100644 --- a/doc/hardware/peripherals/mspi.rst +++ b/doc/hardware/peripherals/mspi.rst @@ -100,10 +100,12 @@ whether to support scatter IO and callback management. The controller can determ which user callback to trigger based on :c:enum:`mspi_bus_event_cb_mask` upon completion of each async/sync transfer if the callback had been registered using :c:func:`mspi_register_callback`. Or not to trigger any callback at all with -:c:enum:`MSPI_BUS_NO_CB` even if the callbacks are already registered. -In which case that a controller supports hardware command queue, user could take full -advantage of the hardware performance if scatter IO and callback management are supported -by the driver implementation. +:c:enum:`MSPI_BUS_NO_CB` even if the callbacks are already registered. If the implemented +driver support it, the API supports :c:enum:`MSPI_BUS_XFER_COMPLETE_CB` to signal when a +transfer finishes and :c:enum:`MSPI_BUS_TIMEOUT_CB` to signal when a transfer or request +has timed-out. In which case that a controller supports hardware command queue, user could +take full advantage of the hardware performance if scatter IO and callback management are +supported by the driver implementation. Device Tree =========== @@ -192,6 +194,7 @@ Related configuration options: * :kconfig:option:`CONFIG_MSPI_TIMING` * :kconfig:option:`CONFIG_MSPI_INIT_PRIORITY` * :kconfig:option:`CONFIG_MSPI_COMPLETION_TIMEOUT_TOLERANCE` +* :kconfig:option:`CONFIG_MSPI_DMA` API Reference ************* diff --git a/doc/kconfig.rst b/doc/kconfig.rst deleted file mode 100644 index 1123de2adbd9..000000000000 --- a/doc/kconfig.rst +++ /dev/null @@ -1,8 +0,0 @@ -:orphan: - -.. _kconfig-search: - -Kconfig Search -============== - -.. kconfig:search:: diff --git a/doc/releases/migration-guide-4.3.rst b/doc/releases/migration-guide-4.3.rst index e2e6c21b57d7..53e6b64ab72d 100644 --- a/doc/releases/migration-guide-4.3.rst +++ b/doc/releases/migration-guide-4.3.rst @@ -91,10 +91,13 @@ Bluetooth Bluetooth Controller ==================== -* The following Kconfig option have been renamed: +* The following have been renamed: * :kconfig:option:`CONFIG_BT_CTRL_ADV_ADI_IN_SCAN_RSP` to :kconfig:option:`CONFIG_BT_CTLR_ADV_ADI_IN_SCAN_RSP` + * :c:struct:`bt_hci_vs_fata_error_cpu_data_cortex_m` to + :c:struct:`bt_hci_vs_fatal_error_cpu_data_cortex_m` and now contains the program counter + value. .. zephyr-keep-sorted-start re(^\w) @@ -120,6 +123,15 @@ Bluetooth HCI * The deprecated ``ipm`` value was removed from ``bt-hci-bus`` devicetree property. ``ipc`` should be used instead. +Bluetooth Host +============== + +* :kconfig:option:`CONFIG_BT_FIXED_PASSKEY` has been deprecated. Instead, the application can + provide passkeys for pairing using the :c:member:`bt_conn_auth_cb.app_passkey` callback, which is + available when :kconfig:option:`CONFIG_BT_APP_PASSKEY` is enabled. The application can return the + passkey for pairing, or :c:macro:`BT_PASSKEY_RAND` for the Host to generate a random passkey + instead. + Ethernet ======== @@ -150,6 +162,13 @@ Networking .. zephyr-keep-sorted-stop +Modem +***** + +* ``CONFIG_MODEM_AT_SHELL_USER_PIPE`` has been renamed to :kconfig:option:`CONFIG_MODEM_AT_USER_PIPE`. +* ``CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE`` has been updated to :kconfig:option:`CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE_EXTRA`, + which only takes the number of extra bytes desired over the default of (:kconfig:option:`CONFIG_MODEM_CMUX_MTU` + 7). + Display ******* diff --git a/doc/releases/migration-guide-4.4.rst b/doc/releases/migration-guide-4.4.rst new file mode 100644 index 000000000000..b10c86e9f23b --- /dev/null +++ b/doc/releases/migration-guide-4.4.rst @@ -0,0 +1,48 @@ +:orphan: + +.. + See + https://docs.zephyrproject.org/latest/releases/index.html#migration-guides + for details of what is supposed to go into this document. + +.. _migration_4.4: + +Migration guide to Zephyr v4.4.0 (Working Draft) +################################################ + +This document describes the changes required when migrating your application from Zephyr v4.3.0 to +Zephyr v4.4.0. + +Any other changes (not directly related to migrating applications) can be found in +the :ref:`release notes`. + +.. contents:: + :local: + :depth: 2 + +Build System +************ + +Kernel +****** + +Boards +****** + +Device Drivers and Devicetree +***************************** + +Bluetooth +********* + +Networking +********** + +Other subsystems +**************** + +Modules +******* + +Architectures +************* diff --git a/doc/releases/release-notes-4.3.rst b/doc/releases/release-notes-4.3.rst index 6dfc304b3ef5..3e9b87db998e 100644 --- a/doc/releases/release-notes-4.3.rst +++ b/doc/releases/release-notes-4.3.rst @@ -61,6 +61,8 @@ Removed APIs and options * The TinyCrypt library was removed as the upstream version is no longer maintained. PSA Crypto API is now the recommended cryptographic library for Zephyr. * The legacy pipe object API was removed. Use the new pipe API instead. +* ``bt_le_set_auto_conn`` +* ``CONFIG_BT_BUF_ACL_RX_COUNT`` Deprecated APIs and options =========================== @@ -171,6 +173,17 @@ New APIs and options * :kconfig:option:`CONFIG_HAWKBIT_REBOOT_NONE` +* Modem + + * :kconfig:option:`CONFIG_MODEM_DEDICATED_WORKQUEUE` + +* Networking + + * Sockets + + * :c:func:`zsock_listen` now implements the ``backlog`` parameter support. The TCP server + socket will limit the number of pending incoming connections to that value. + * Power management * :c:func:`pm_device_driver_deinit` diff --git a/doc/releases/release-notes-4.4.rst b/doc/releases/release-notes-4.4.rst new file mode 100644 index 000000000000..d6277acc7161 --- /dev/null +++ b/doc/releases/release-notes-4.4.rst @@ -0,0 +1,135 @@ +:orphan: + +.. + What goes here: removed/deprecated apis, new boards, new drivers, notable + features. If you feel like something new can be useful to a user, put it + under "Other Enhancements" in the first paragraph, if you feel like something + is worth mentioning in the project media (release blog post, release + livestream) put it under "Major enhancement". +.. + If you are describing a feature or functionality, consider adding it to the + actual project documentation rather than the release notes, so that the + information does not get lost in time. +.. + No list of bugfixes, minor changes, those are already in the git log, this is + not a changelog. +.. + Does the entry have a link that contains the details? Just add the link, if + you think it needs more details, put them in the content that shows up on the + link. +.. + Are you thinking about generating this? Don't put anything at all. +.. + Does the thing require the user to change their application? Put it on the + migration guide instead. (TODO: move the removed APIs section in the + migration guide) + +.. _zephyr_4.4: + +Zephyr 4.4.0 (Working Draft) +############################ + +We are pleased to announce the release of Zephyr version 4.4.0. + +Major enhancements with this release include: + +An overview of the changes required or recommended when migrating your application from Zephyr +v4.3.0 to Zephyr v4.4.0 can be found in the separate :ref:`migration guide`. + +The following sections provide detailed lists of changes by component. + +Security Vulnerability Related +****************************** + +API Changes +*********** + +.. + Only removed, deprecated and new APIs. Changes go in migration guide. + +Removed APIs and options +======================== + +Deprecated APIs and options +=========================== + +* Bluetooth + + * Mesh + + * The function :c:func:`bt_mesh_input_number` was deprecated. Applications should use + :c:func:`bt_mesh_input_numeric` instead. + * The callback :c:member:`output_number` in :c:struct:`bt_mesh_prov` structure was deprecated. + Applications should use :c:member:`output_numeric` callback instead. + +New APIs and options +==================== + +.. + Link to new APIs here, in a group if you think it's necessary, no need to get + fancy just list the link, that should contain the documentation. If you feel + like you need to add more details, add them in the API documentation code + instead. + +.. zephyr-keep-sorted-start re(^\* \w) + +* Bluetooth + + * Mesh + + * :c:func:`bt_mesh_input_numeric` to provide provisioning numeric input OOB value. + * :c:member:`output_numeric` callback in :c:struct:`bt_mesh_prov` structure to + output numeric values during provisioning. + + * Services + + * Introduced Alert Notification Service (ANS) :kconfig:option:`CONFIG_BT_ANS` + +* Flash + + * :dtcompatible:`jedec,mspi-nor` now allows MSPI configuration of read, write and + control commands separately via devicetree. + +.. zephyr-keep-sorted-stop + +New Boards +********** + +.. + You may update this list as you contribute a new board during the release cycle, in order to make + it visible to people who might be looking at the working draft of the release notes. However, note + that this list will be recomputed at the time of the release, so you don't *have* to update it. + In any case, just link the board, further details go in the board description. + +New Shields +*********** + +.. + Same as above, this will also be recomputed at the time of the release. + +New Drivers +*********** + +.. + Same as above, this will also be recomputed at the time of the release. + Just link the driver, further details go in the binding description + +New Samples +*********** + +* :zephyr:code-sample:`ble_peripheral_ans` + +.. + Same as above, this will also be recomputed at the time of the release. + Just link the sample, further details go in the sample documentation itself. + + +Libraries / Subsystems +********************** + +Other notable changes +********************* + +.. + Any more descriptive subsystem or driver changes. Do you really want to write + a paragraph or is it enough to link to the api/driver/Kconfig/board page above? diff --git a/doc/services/logging/cs_stm.rst b/doc/services/logging/cs_stm.rst index 75a371dfd24e..77b097d65161 100644 --- a/doc/services/logging/cs_stm.rst +++ b/doc/services/logging/cs_stm.rst @@ -119,7 +119,7 @@ When using logs, this method has the following advantages: Proxy core is using Nordic specific peripheral (TBM) to get ETR buffer busyness and send data over UART. Nordic specific driver for ETR buffer is located in -:zephyr_file:`drivers/misc/coresight/nrf_etr.c`. +:zephyr_file:`drivers/debug/debug_nrf_etr.c`. Configuration ------------- @@ -175,7 +175,7 @@ in :zephyr_file:`subsys/logging/frontends/log_frontend_stmesp_demux.c`. ``Proxy`` is using Nordic specific peripheral (TBM) to get ETR buffer busyness and read and decode data and send human-readable data over UART. Nordic specific driver for ETR buffer is -located in :zephyr_file:`drivers/misc/coresight/nrf_etr.c`. It is using :ref:`cs_trace_defmt` and +located in :zephyr_file:`drivers/debug/debug_nrf_etr.c`. It is using :ref:`cs_trace_defmt` and :ref:`mipi_stp_decoder` and above-mentioned demultiplexer to decode messages. Logging messages contains read-only format string used in the logging macros thus they cannot be diff --git a/drivers/adc/adc_nrfx_saadc.c b/drivers/adc/adc_nrfx_saadc.c index 06035e2c3c5d..32be9825d243 100644 --- a/drivers/adc/adc_nrfx_saadc.c +++ b/drivers/adc/adc_nrfx_saadc.c @@ -12,7 +12,11 @@ #include #include #include +#include +#include #include +#include +#include LOG_MODULE_REGISTER(adc_nrfx_saadc, CONFIG_ADC_LOG_LEVEL); @@ -197,6 +201,10 @@ static int input_assign(nrf_saadc_input_t *pin_p, *pin_p = saadc_psels[channel_cfg->input_positive]; +#if NRF_GPIO_HAS_RETENTION_SETCLEAR + nrf_gpio_pin_retain_disable(saadc_psels[channel_cfg->input_positive]); +#endif + if (channel_cfg->differential) { if (channel_cfg->input_negative > ARRAY_SIZE(saadc_psels) || (IS_ENABLED(CONFIG_NRF_PLATFORM_HALTIUM) && @@ -209,6 +217,12 @@ static int input_assign(nrf_saadc_input_t *pin_p, *pin_n = channel_cfg->input_negative == NRF_SAADC_GND ? NRF_SAADC_INPUT_DISABLED : saadc_psels[channel_cfg->input_negative]; + +#if NRF_GPIO_HAS_RETENTION_SETCLEAR + if (channel_cfg->input_negative != NRF_SAADC_GND) { + nrf_gpio_pin_retain_disable(saadc_psels[channel_cfg->input_negative]); + } +#endif } else { *pin_n = NRF_SAADC_INPUT_DISABLED; } @@ -724,10 +738,19 @@ static int adc_nrfx_read(const struct device *dev, { int error; + error = pm_device_runtime_get(dev); + if (error) { + return error; + } + adc_context_lock(&m_data.ctx, false, NULL); error = start_read(dev, sequence); adc_context_release(&m_data.ctx, error); + if (pm_device_runtime_put(dev)) { + LOG_ERR("PM put failed"); + } + return error; } @@ -777,6 +800,13 @@ static void event_handler(const nrfx_saadc_evt_t *event) } } +static int saadc_pm_handler(const struct device *dev, enum pm_device_action action) +{ + ARG_UNUSED(dev); + ARG_UNUSED(action); + return 0; +} + static int init_saadc(const struct device *dev) { nrfx_err_t err; @@ -794,7 +824,7 @@ static int init_saadc(const struct device *dev) adc_context_unlock_unconditionally(&m_data.ctx); - return 0; + return pm_device_driver_init(dev, saadc_pm_handler); } static DEVICE_API(adc, adc_nrfx_driver_api) = { @@ -837,5 +867,7 @@ DT_FOREACH_CHILD(DT_DRV_INST(0), VALIDATE_CHANNEL_CONFIG) NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(DT_DRV_INST(0)); -DEVICE_DT_INST_DEFINE(0, init_saadc, NULL, NULL, NULL, POST_KERNEL, - CONFIG_ADC_INIT_PRIORITY, &adc_nrfx_driver_api); +PM_DEVICE_DT_INST_DEFINE(0, saadc_pm_handler); +DEVICE_DT_INST_DEFINE(0, init_saadc, PM_DEVICE_DT_INST_GET(0), NULL, + NULL, POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, + &adc_nrfx_driver_api); diff --git a/drivers/audio/dmic_nrfx_pdm.c b/drivers/audio/dmic_nrfx_pdm.c index f0162fc5ef8b..a2d630f847a9 100644 --- a/drivers/audio/dmic_nrfx_pdm.c +++ b/drivers/audio/dmic_nrfx_pdm.c @@ -24,11 +24,15 @@ LOG_MODULE_REGISTER(dmic_nrfx_pdm, CONFIG_AUDIO_DMIC_LOG_LEVEL); #define DMIC_NRFX_CLOCK_FACTOR 8192 #define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP_OR(NODE_AUDIOPLL, frequency, 0) #elif DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) -#define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP(NODE_AUDIO_AUXPLL, nordic_frequency) -BUILD_ASSERT((DMIC_NRFX_AUDIO_CLOCK_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_48K) || - (DMIC_NRFX_AUDIO_CLOCK_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1), +#define AUXPLL_FREQUENCY_SETTING DT_PROP(NODE_AUDIO_AUXPLL, nordic_frequency) +BUILD_ASSERT((AUXPLL_FREQUENCY_SETTING == NRF_AUXPLL_FREQ_DIV_AUDIO_48K) || + (AUXPLL_FREQUENCY_SETTING == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1), "Unsupported Audio AUXPLL frequency selection for PDM"); + +#define DMIC_NRFX_AUDIO_CLOCK_FREQ CLOCK_CONTROL_NRF_AUXPLL_GET_FREQ(NODE_AUDIO_AUXPLL) + #define DMIC_NRFX_CLOCK_FREQ MHZ(32) + #else #define DMIC_NRFX_CLOCK_FREQ MHZ(32) #define DMIC_NRFX_CLOCK_FACTOR 4096 @@ -668,11 +672,12 @@ static int dmic_nrfx_pdm_read(const struct device *dev, static void init_clock_manager(const struct device *dev) { - struct dmic_nrfx_pdm_drv_data *drv_data = dev->data; #if DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) + struct dmic_nrfx_pdm_drv_data *drv_data = dev->data; drv_data->audiopll_dev = DEVICE_DT_GET(NODE_AUDIO_AUXPLL); #elif CONFIG_CLOCK_CONTROL_NRF clock_control_subsys_t subsys; + struct dmic_nrfx_pdm_drv_data *drv_data = dev->data; #if NRF_CLOCK_HAS_HFCLKAUDIO const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index a1680af6583d..e64a33f663ce 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -12,7 +12,7 @@ menuconfig BT_DRIVERS bool "Bluetooth drivers" default y - depends on BT + depends on BT && BT_HCI if BT_DRIVERS diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig index f1d1939259dc..92f4d4fa3d71 100644 --- a/drivers/bluetooth/hci/Kconfig +++ b/drivers/bluetooth/hci/Kconfig @@ -158,9 +158,7 @@ config BT_SILABS_EFR32 depends on ZEPHYR_HAL_SILABS_MODULE_BLOBS || BUILD_ONLY_NO_BLOBS depends on !PM || SOC_GECKO_PM_BACKEND_PMGR select SOC_GECKO_USE_RAIL - select MBEDTLS - select MBEDTLS_PSA_CRYPTO_C - select MBEDTLS_ENTROPY_C + select PSA_CRYPTO select HAS_BT_CTLR select BT_CTLR_PHY_UPDATE_SUPPORT select BT_CTLR_PER_INIT_FEAT_XCHG_SUPPORT diff --git a/drivers/bluetooth/hci/Kconfig.esp32 b/drivers/bluetooth/hci/Kconfig.esp32 index 9f363ebc700f..501c5238db79 100644 --- a/drivers/bluetooth/hci/Kconfig.esp32 +++ b/drivers/bluetooth/hci/Kconfig.esp32 @@ -492,7 +492,6 @@ config ESP32_BT_LE_CRYPTO_STACK_MBEDTLS select MBEDTLS_ECP_DP_SECP256R1_ENABLED select MBEDTLS_ECDH_C select MBEDTLS_ENTROPY_C - select MBEDTLS_PSA_CRYPTO_C help Use mbedTLS library for BLE cryptographic operations. diff --git a/drivers/bluetooth/hci/h4.c b/drivers/bluetooth/hci/h4.c index cfea346a946c..21be2213fb87 100644 --- a/drivers/bluetooth/hci/h4.c +++ b/drivers/bluetooth/hci/h4.c @@ -338,7 +338,7 @@ static inline void read_payload(const struct device *dev) LOG_DBG("Allocated rx.buf %p", h4->rx.buf); buf_tailroom = net_buf_tailroom(h4->rx.buf); - if (buf_tailroom < h4->rx.remaining) { + if (buf_tailroom < (h4->rx.remaining + h4->rx.hdr_len)) { LOG_ERR("Not enough space in buffer %u/%zu", h4->rx.remaining, buf_tailroom); h4->rx.discard = h4->rx.remaining; diff --git a/drivers/bluetooth/hci/hci_spi_st.c b/drivers/bluetooth/hci/hci_spi_st.c index 8f6bf72c0edb..5b0d8fc674af 100644 --- a/drivers/bluetooth/hci/hci_spi_st.c +++ b/drivers/bluetooth/hci/hci_spi_st.c @@ -515,7 +515,11 @@ static void bt_spi_rx_thread(void *p1, void *p2, void *p3) while (true) { /* Wait for interrupt pin to be active */ - k_sem_take(&sem_request, K_FOREVER); + ret = k_sem_take(&sem_request, K_FOREVER); + if (ret) { + LOG_DBG("Failed to take the semaphore. The RX thread exits."); + break; + } LOG_DBG(""); @@ -685,12 +689,39 @@ static int bt_spi_open(const struct device *dev, bt_hci_recv_t recv) return 0; } +static int bt_spi_close(const struct device *dev) +{ + struct bt_spi_data *hci = dev->data; + int ret; + + gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_DISABLE); + + /* To exit the thread safely */ + k_sem_reset(&sem_request); + ret = k_thread_join(&spi_rx_thread_data, K_MSEC(100)); + if (ret) { + LOG_DBG("bt_spi_rx_thread is unable to exit"); + return ret; + } + + /* Reset the BLE controller */ + gpio_pin_set_dt(&rst_gpio, 1); + k_sleep(K_MSEC(DT_INST_PROP_OR(0, reset_assert_duration_ms, 0))); + gpio_pin_set_dt(&rst_gpio, 0); + + hci->recv = NULL; + LOG_DBG("Bluetooth disabled"); + + return 0; +} + static DEVICE_API(bt_hci, drv) = { #if defined(CONFIG_BT_BLUENRG_ACI) && !defined(CONFIG_BT_HCI_RAW) .setup = bt_spi_bluenrg_setup, #endif /* CONFIG_BT_BLUENRG_ACI && !CONFIG_BT_HCI_RAW */ .open = bt_spi_open, .send = bt_spi_send, + .close = bt_spi_close, }; static int bt_spi_init(const struct device *dev) diff --git a/drivers/can/Kconfig.mcan b/drivers/can/Kconfig.mcan index db09fc800c11..96c5f22446f6 100644 --- a/drivers/can/Kconfig.mcan +++ b/drivers/can/Kconfig.mcan @@ -7,3 +7,18 @@ config CAN_MCAN bool help Enable the Bosch M_CAN CAN IP module driver backend. + +if CAN_MCAN + +config CAN_MCAN_TXBCF_POLL_INTERVAL_MS + int "Polling interval in milliseconds of TXBCF register if DAR is enabled" + default 75 + help + When DAR (Disable Automatic Retransmission), used for CAN_MODE_ONE_SHOT, + is enabled, and a transmission fails, a bug in the MCAN IP prevents the + TCF (Transmission Cancellation Finalized) interrupt from triggering, + despite the correct bit being set in the TXBCF register. It is thus + necessary to poll TXBCF register to detect when a transmission failed if + DAR is enabled. + +endif # CAN_MCAN diff --git a/drivers/can/can_mcan.c b/drivers/can/can_mcan.c index 3f7d771e5f4a..e82cac4f19ad 100644 --- a/drivers/can/can_mcan.c +++ b/drivers/can/can_mcan.c @@ -10,12 +10,14 @@ #include #include #include +#include #include #include LOG_MODULE_REGISTER(can_mcan, CONFIG_CAN_LOG_LEVEL); #define CAN_INIT_TIMEOUT_MS 100 +#define TXBCF_TIMER_TIMEOUT K_MSEC(CONFIG_CAN_MCAN_TXBCF_POLL_INTERVAL_MS) int can_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val) { @@ -275,7 +277,7 @@ int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap) { ARG_UNUSED(dev); - *cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY; + *cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_ONE_SHOT; if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) { *cap |= CAN_MODE_MANUAL_RECOVERY; @@ -321,11 +323,99 @@ int can_mcan_start(const struct device *dev) return err; } + uint32_t cccr; + + err = can_mcan_read_reg(dev, CAN_MCAN_CCCR, &cccr); + if (err != 0) { + return err; + } + + if (cccr & CAN_MCAN_CCCR_DAR) { + /* + * When DAR (Disable Automatic Retransmission), used for CAN_MODE_ONE_SHOT, + * is enabled, and a transmission fails, a bug in the MCAN IP prevents the + * TCF (Transmission Cancellation Finalized) interrupt from triggering, + * despite the correct bit being set in the TXBCF register. It is thus + * necessary to poll TXBCF register to detect when a transmission failed if + * DAR is enabled. + */ + k_timer_start(&data->txbcf_timer, TXBCF_TIMER_TIMEOUT, TXBCF_TIMER_TIMEOUT); + } + data->common.started = true; + pm_device_busy_set(dev); return err; } +static int can_mcan_read_txbcf(const struct device *dev) +{ + const struct can_mcan_config *config = dev->config; + const struct can_mcan_callbacks *cbs = config->callbacks; + struct can_mcan_data *data = dev->data; + uint32_t txbcfs; + int err; + can_tx_callback_t tx_cb; + void *user_data; + + err = can_mcan_read_reg(dev, CAN_MCAN_TXBCF, &txbcfs); + if (err != 0) { + LOG_ERR("failed to read tx cancellation finished (err %d)", err); + return err; + } + + if (txbcfs == 0) { + return 0; + } + + for (size_t tx_idx = 0; tx_idx < cbs->num_tx; tx_idx++) { + if ((txbcfs & BIT(tx_idx)) == 0) { + continue; + } + + if (cbs->tx[tx_idx].function == NULL) { + continue; + } + + tx_cb = cbs->tx[tx_idx].function; + user_data = cbs->tx[tx_idx].user_data; + cbs->tx[tx_idx].function = NULL; + LOG_DBG("tx buffer cancellation finished (idx %u)", tx_idx); + k_sem_give(&data->tx_sem); + tx_cb(dev, -EIO, user_data); + } + + return 0; +} + +static void can_mcan_txbcf_timer_handler(struct k_timer *timer_id) +{ + const struct device *dev = k_timer_user_data_get(timer_id); + + can_mcan_read_txbcf(dev); +} + +static bool can_mcan_rx_filters_exist(const struct device *dev) +{ + const struct can_mcan_config *config = dev->config; + const struct can_mcan_callbacks *cbs = config->callbacks; + int i; + + for (i = 0; i < cbs->num_std; i++) { + if (cbs->std[i].function != NULL) { + return true; + } + } + + for (i = 0; i < cbs->num_ext; i++) { + if (cbs->ext[i].function != NULL) { + return true; + } + } + + return false; +} + int can_mcan_stop(const struct device *dev) { const struct can_mcan_config *config = dev->config; @@ -339,6 +429,8 @@ int can_mcan_stop(const struct device *dev) return -EALREADY; } + k_timer_stop(&data->txbcf_timer); + /* CAN transmissions are automatically stopped when entering init mode */ err = can_mcan_enter_init_mode(dev, K_MSEC(CAN_INIT_TIMEOUT_MS)); if (err != 0) { @@ -368,12 +460,18 @@ int can_mcan_stop(const struct device *dev) } } + k_mutex_lock(&data->lock, K_FOREVER); + if (!can_mcan_rx_filters_exist(dev)) { + pm_device_busy_clear(dev); + } + k_mutex_unlock(&data->lock); + return 0; } int can_mcan_set_mode(const struct device *dev, can_mode_t mode) { - can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY; + can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_ONE_SHOT; struct can_mcan_data *data = dev->data; uint32_t cccr; uint32_t test; @@ -431,6 +529,13 @@ int can_mcan_set_mode(const struct device *dev, can_mode_t mode) } #endif /* CONFIG_CAN_FD_MODE */ + if ((mode & CAN_MODE_ONE_SHOT) != 0) { + /* Disable Automatic Retransmission */ + cccr |= CAN_MCAN_CCCR_DAR; + } else { + cccr &= ~CAN_MCAN_CCCR_DAR; + } + err = can_mcan_write_reg(dev, CAN_MCAN_CCCR, cccr); if (err != 0) { goto unlock; @@ -1024,6 +1129,21 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim } } + uint32_t cccr; + + err = can_mcan_read_reg(dev, CAN_MCAN_CCCR, &cccr); + if (err != 0) { + return err; + } + + if (cccr & CAN_MCAN_CCCR_DAR) { + /* + * TXBCR is cleared after TXBAR is set. Stop timer to ensure + * TXBCR is not read before TXBAR has been set. + */ + k_timer_stop(&data->txbcf_timer); + } + __ASSERT_NO_MSG(put_idx < cbs->num_tx); cbs->tx[put_idx].function = callback; cbs->tx[put_idx].user_data = user_data; @@ -1034,10 +1154,18 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim goto err_unlock; } + if (cccr & CAN_MCAN_CCCR_DAR) { + k_timer_start(&data->txbcf_timer, TXBCF_TIMER_TIMEOUT, TXBCF_TIMER_TIMEOUT); + } + k_mutex_unlock(&data->tx_mtx); return 0; err_unlock: + if (cccr & CAN_MCAN_CCCR_DAR) { + k_timer_start(&data->txbcf_timer, TXBCF_TIMER_TIMEOUT, TXBCF_TIMER_TIMEOUT); + } + k_mutex_unlock(&data->tx_mtx); k_sem_give(&data->tx_sem); @@ -1184,6 +1312,8 @@ int can_mcan_add_rx_filter(const struct device *dev, can_rx_callback_t callback, filter_id = can_mcan_add_rx_filter_std(dev, callback, user_data, filter); } + pm_device_busy_set(dev); + return filter_id; } @@ -1230,6 +1360,10 @@ void can_mcan_remove_rx_filter(const struct device *dev, int filter_id) } } + if (!can_mcan_rx_filters_exist(dev) && !data->common.started) { + pm_device_busy_clear(dev); + } + k_mutex_unlock(&data->lock); } @@ -1389,6 +1523,8 @@ int can_mcan_init(const struct device *dev) k_mutex_init(&data->lock); k_mutex_init(&data->tx_mtx); k_sem_init(&data->tx_sem, cbs->num_tx, cbs->num_tx); + k_timer_init(&data->txbcf_timer, can_mcan_txbcf_timer_handler, NULL); + k_timer_user_data_set(&data->txbcf_timer, (void *)dev); if (config->common.phy != NULL && !device_is_ready(config->common.phy)) { LOG_ERR("CAN transceiver not ready"); @@ -1530,5 +1666,14 @@ int can_mcan_init(const struct device *dev) return err; } + /* + * Interrupt on every TX buffer cancellation finished event. + */ + reg = CAN_MCAN_TXBCIE_CFIE; + err = can_mcan_write_reg(dev, CAN_MCAN_TXBCIE, reg); + if (err != 0) { + return err; + } + return can_mcan_clear_mram(dev, 0, config->mram_size); } diff --git a/drivers/can/can_nrf.c b/drivers/can/can_nrf.c index 8e19b5420356..fa287b301ed1 100644 --- a/drivers/can/can_nrf.c +++ b/drivers/can/can_nrf.c @@ -29,7 +29,6 @@ struct can_nrf_config { uint32_t mrba; uint32_t mram; const struct device *auxpll; - const struct device *hsfll; const struct pinctrl_dev_config *pcfg; void (*irq_configure)(void); uint16_t irq; @@ -133,40 +132,16 @@ static const struct can_mcan_ops can_mcan_nrf_ops = { .clear_mram = can_nrf_clear_mram, }; -static int configure_hsfll(const struct device *dev, bool on) -{ - const struct can_mcan_config *mcan_config = dev->config; - const struct can_nrf_config *config = mcan_config->custom; - struct nrf_clock_spec spec = { 0 }; - - /* If CAN is on, HSFLL frequency >= AUXPLL frequency */ - if (on) { - int ret; - - ret = clock_control_get_rate(config->auxpll, NULL, &spec.frequency); - if (ret < 0) { - return ret; - } - } - - return nrf_clock_control_request_sync(config->hsfll, &spec, K_FOREVER); -} - static int can_nrf_init(const struct device *dev) { const struct can_mcan_config *mcan_config = dev->config; const struct can_nrf_config *config = mcan_config->custom; int ret; - if (!device_is_ready(config->auxpll) || !device_is_ready(config->hsfll)) { + if (!device_is_ready(config->auxpll)) { return -ENODEV; } - ret = configure_hsfll(dev, true); - if (ret < 0) { - return ret; - } - ret = nrf_clock_control_request_sync(config->auxpll, NULL, K_FOREVER); if (ret < 0) { return ret; @@ -215,7 +190,6 @@ static int can_nrf_init(const struct device *dev) .mram = CAN_MCAN_DT_INST_MRAM_ADDR(n), \ .auxpll = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(n, auxpll)), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - .hsfll = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(n, hsfll)), \ .irq = DT_INST_IRQN(n), \ .irq_configure = can_nrf_irq_configure##n, \ }; \ @@ -227,8 +201,8 @@ static int can_nrf_init(const struct device *dev) \ static struct can_mcan_data can_mcan_nrf_data##n = CAN_MCAN_DATA_INITIALIZER(NULL); \ \ - DEVICE_DT_INST_DEFINE(n, can_nrf_init, NULL, &can_mcan_nrf_data##n, \ - &can_mcan_nrf_config##n, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &can_nrf_api); + CAN_DEVICE_DT_INST_DEFINE(n, can_nrf_init, NULL, &can_mcan_nrf_data##n, \ + &can_mcan_nrf_config##n, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &can_nrf_api); DT_INST_FOREACH_STATUS_OKAY(CAN_NRF_DEFINE) diff --git a/drivers/can/can_tcan4x5x.c b/drivers/can/can_tcan4x5x.c index 2abd0467a5ee..31f61b7dd72d 100644 --- a/drivers/can/can_tcan4x5x.c +++ b/drivers/can/can_tcan4x5x.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include LOG_MODULE_REGISTER(can_tcan4x5x, CONFIG_CAN_LOG_LEVEL); @@ -100,6 +102,10 @@ LOG_MODULE_REGISTER(can_tcan4x5x, CONFIG_CAN_LOG_LEVEL); #define CAN_TCAN4X5X_MODE_CONFIG_SWE_DIS BIT(1) #define CAN_TCAN4X5X_MODE_CONFIG_TEST_MODE_CONFIG BIT(0) +#define CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_SLEEP 0 +#define CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_STANDBY 1 +#define CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_NORMAL 2 + /* Timestamp Prescaler register */ #define CAN_TCAN4X5X_TIMESTAMP_PRESCALER 0x0804 #define CAN_TCAN4X5X_TIMESTAMP_PRESCALER_MASK GENMASK(7, 0) @@ -201,6 +207,9 @@ LOG_MODULE_REGISTER(can_tcan4x5x, CONFIG_CAN_LOG_LEVEL); /* TCAN4x5x timing requirements */ #define CAN_TCAN4X5X_T_MODE_STBY_NOM_US 70 +#define CAN_TCAN4X5X_T_MODE_NOM_SLP_US 200 +#define CAN_TCAN4X5X_T_MODE_NOM_STBY_US 200 +#define CAN_TCAN4X5X_T_MODE_SLP_STBY_US 200 #define CAN_TCAN4X5X_T_WAKE_US 50 #define CAN_TCAN4X5X_T_PULSE_WIDTH_US 30 #define CAN_TCAN4X5X_T_RESET_US 1000 @@ -551,6 +560,154 @@ static int tcan4x5x_reset(const struct device *dev) return 0; } +static int tcan4x5x_set_config_mode_sel(const struct device *dev, uint8_t mode, uint32_t *reg) +{ + int err; + uint8_t current_mode; + + switch (mode) { + case CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_SLEEP: + case CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_STANDBY: + case CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_NORMAL: + break; + default: + LOG_ERR("invalid mode %u", mode); + return -EINVAL; + } + + err = tcan4x5x_read_tcan_reg(dev, CAN_TCAN4X5X_MODE_CONFIG, reg); + if (err != 0) { + LOG_ERR("failed to read configuration register (err %d)", err); + return -EIO; + } + + current_mode = FIELD_GET(CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL, *reg); + LOG_DBG("current mode %u, new mode %u", current_mode, mode); + + *reg &= ~(CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL); + *reg |= FIELD_PREP(CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL, mode); + + err = tcan4x5x_write_tcan_reg(dev, CAN_TCAN4X5X_MODE_CONFIG, *reg); + if (err != 0) { + LOG_ERR("failed to write configuration register (err %d)", err); + return -EIO; + } + + if (current_mode == CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_STANDBY && + mode == CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_NORMAL) { + /* Wait for standby to normal mode switch */ + k_busy_wait(CAN_TCAN4X5X_T_MODE_STBY_NOM_US); + } else if (current_mode == CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_NORMAL && + mode == CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_SLEEP) { + /* Wait for normal to sleep mode switch */ + k_busy_wait(CAN_TCAN4X5X_T_MODE_NOM_SLP_US); + } else if (current_mode == CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_NORMAL && + mode == CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_STANDBY) { + /* Wait for normal to standby mode switch */ + k_busy_wait(CAN_TCAN4X5X_T_MODE_NOM_STBY_US); + } else if (current_mode == CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_SLEEP && + mode == CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_STANDBY) { + /* Wait for sleep to standby mode switch */ + k_busy_wait(CAN_TCAN4X5X_T_MODE_SLP_STBY_US); + } + + return 0; +} + +static int tcan4x5x_init_normal_mode(const struct device *dev) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct tcan4x5x_config *tcan_config = mcan_config->custom; + int err = 0; + uint32_t reg; + + /* Set TCAN4x5x mode normal */ + err = tcan4x5x_set_config_mode_sel(dev, CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_NORMAL, ®); + if (err != 0) { + return -ENODEV; + } + + /* Configure the frequency reference */ + if (tcan_config->clk_freq == MHZ(20)) { + /* 20 MHz frequency reference */ + reg &= ~(CAN_TCAN4X5X_MODE_CONFIG_CLK_REF); + } else { + /* 40 MHz frequency reference */ + reg |= CAN_TCAN4X5X_MODE_CONFIG_CLK_REF; + } + + /* Set nWKRQ voltage to VIO */ + reg |= CAN_TCAN4X5X_MODE_CONFIG_NWKRQ_VOLTAGE; + + /* Write remaining configuration to the device */ + err = tcan4x5x_write_tcan_reg(dev, CAN_TCAN4X5X_MODE_CONFIG, reg); + if (err != 0) { + LOG_ERR("failed to write configuration register (err %d)", err); + return -EIO; + } + + /* Configure Message RAM */ + err = can_mcan_configure_mram(dev, CAN_TCAN4X5X_MRAM_BASE, CAN_TCAN4X5X_MRAM_BASE); + if (err != 0) { + return -EIO; + } + + /* Initialize M_CAN */ + err = can_mcan_init(dev); + if (err != 0) { + LOG_ERR("failed to initialize mcan (err %d)", err); + return err; + } + + return err; +} + +#ifdef CONFIG_PM_DEVICE +static int tcan4x5x_pm_control(const struct device *dev, enum pm_device_action action) +{ + int err = 0; + uint32_t reg; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + if (pm_device_is_busy(dev)) { + LOG_DBG("Cannot suspend while device is busy"); + return -EBUSY; + } + + /* + * Enter sleep mode. + * NOTE: All RX filters are cleared when entering sleep mode. + * User must remove and re-add filters at the application layer. + */ + err = tcan4x5x_set_config_mode_sel(dev, CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL_SLEEP, + ®); + return err; + case PM_DEVICE_ACTION_RESUME: + /* Wake up the device */ +#if TCAN4X5X_WAKE_GPIO_SUPPORT + LOG_DBG("Waking up TCAN4x5x via WAKE GPIO"); + err = tcan4x5x_wake(dev); + if (err != 0) { + return err; + } +#else + LOG_DBG("Waking up TCAN4x5x via reset"); + err = tcan4x5x_reset(dev); + if (err != 0) { + return err; + } +#endif + /* Enter normal mode */ + return tcan4x5x_init_normal_mode(dev); + default: + break; + } + + return -ENOTSUP; +} +#endif /* CONFIG_PM_DEVICE */ + static int tcan4x5x_init(const struct device *dev) { const struct can_mcan_config *mcan_config = dev->config; @@ -558,7 +715,6 @@ static int tcan4x5x_init(const struct device *dev) struct can_mcan_data *mcan_data = dev->data; struct tcan4x5x_data *tcan_data = mcan_data->custom; k_tid_t tid; - uint32_t reg; int err; /* Initialize int_sem to 1 to ensure any pending IRQ is serviced */ @@ -671,48 +827,7 @@ static int tcan4x5x_init(const struct device *dev) FIELD_GET(GENMASK(15, 8), info[2]), FIELD_GET(GENMASK(7, 0), info[2])); #endif /* CONFIG_CAN_LOG_LEVEL >= LOG_LEVEL_DBG */ - /* Set TCAN4x5x mode normal */ - err = tcan4x5x_read_tcan_reg(dev, CAN_TCAN4X5X_MODE_CONFIG, ®); - if (err != 0) { - LOG_ERR("failed to read configuration register (err %d)", err); - return -ENODEV; - } - - reg &= ~(CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL); - reg |= FIELD_PREP(CAN_TCAN4X5X_MODE_CONFIG_MODE_SEL, 0x02); - reg |= CAN_TCAN4X5X_MODE_CONFIG_WAKE_CONFIG; - - if (tcan_config->clk_freq == MHZ(20)) { - /* 20 MHz frequency reference */ - reg &= ~(CAN_TCAN4X5X_MODE_CONFIG_CLK_REF); - } else { - /* 40 MHz frequency reference */ - reg |= CAN_TCAN4X5X_MODE_CONFIG_CLK_REF; - } - - err = tcan4x5x_write_tcan_reg(dev, CAN_TCAN4X5X_MODE_CONFIG, reg); - if (err != 0) { - LOG_ERR("failed to write configuration register (err %d)", err); - return -ENODEV; - } - - /* Wait for standby to normal mode switch */ - k_busy_wait(CAN_TCAN4X5X_T_MODE_STBY_NOM_US); - - /* Configure Message RAM */ - err = can_mcan_configure_mram(dev, CAN_TCAN4X5X_MRAM_BASE, CAN_TCAN4X5X_MRAM_BASE); - if (err != 0) { - return -EIO; - } - - /* Initialize M_CAN */ - err = can_mcan_init(dev); - if (err != 0) { - LOG_ERR("failed to initialize mcan (err %d)", err); - return err; - } - - return 0; + return tcan4x5x_init_normal_mode(dev); } static DEVICE_API(can, tcan4x5x_driver_api) = { @@ -794,8 +909,9 @@ static const struct can_mcan_ops tcan4x5x_ops = { static struct can_mcan_data can_mcan_data_##inst = \ CAN_MCAN_DATA_INITIALIZER(&tcan4x5x_data_##inst); \ \ - CAN_DEVICE_DT_INST_DEFINE(inst, tcan4x5x_init, NULL, &can_mcan_data_##inst, \ - &can_mcan_config_##inst, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ - &tcan4x5x_driver_api); + PM_DEVICE_DT_INST_DEFINE(inst, tcan4x5x_pm_control); \ + CAN_DEVICE_DT_INST_DEFINE(inst, tcan4x5x_init, PM_DEVICE_DT_INST_GET(inst), \ + &can_mcan_data_##inst, &can_mcan_config_##inst, POST_KERNEL, \ + CONFIG_CAN_INIT_PRIORITY, &tcan4x5x_driver_api); DT_INST_FOREACH_STATUS_OKAY(TCAN4X5X_INIT) diff --git a/drivers/clock_control/clock_control_nrf_lfclk.c b/drivers/clock_control/clock_control_nrf_lfclk.c index 9551fb4e6361..dbf7f66e2e25 100644 --- a/drivers/clock_control/clock_control_nrf_lfclk.c +++ b/drivers/clock_control/clock_control_nrf_lfclk.c @@ -25,38 +25,25 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, #define LFCLK_LFRC_STARTUP_TIME_US DT_INST_PROP(0, lfrc_startup_time_us) #define LFCLK_MAX_OPTS 4 -#define LFCLK_DEF_OPTS 2 #define NRFS_CLOCK_TIMEOUT K_MSEC(CONFIG_CLOCK_CONTROL_NRF_LFCLK_CLOCK_TIMEOUT_MS) #define BICR (NRF_BICR_Type *)DT_REG_ADDR(DT_NODELABEL(bicr)) -/* Clock options sorted from highest to lowest power consumption. - * - Clock synthesized from a high frequency clock +/* + * Clock options sorted from lowest to highest power consumption. If clock option + * is not available it is not included. + * - External sine or square wave + * - XTAL low precision + * - XTAL high precision * - Internal RC oscillator - * - External clock. These are inserted into the list at driver initialization. - * Set to one of the following: - * - XTAL. Low or High precision - * - External sine or square wave + * - Clock synthesized from a high frequency clock */ static struct clock_options { uint16_t accuracy : 15; uint16_t precision : 1; nrfs_clock_src_t src; -} clock_options[LFCLK_MAX_OPTS] = { - { - /* NRFS will request FLL16M use HFXO in bypass mode if SYNTH src is used */ - .accuracy = LFCLK_HFXO_ACCURACY, - .precision = 1, - .src = NRFS_CLOCK_SRC_LFCLK_SYNTH, - }, - { - .accuracy = LFCLK_LFRC_ACCURACY, - .precision = 0, - .src = NRFS_CLOCK_SRC_LFCLK_LFRC, - }, - /* Remaining options are populated on lfclk_init */ -}; +} clock_options[LFCLK_MAX_OPTS]; struct lfclk_dev_data { STRUCT_CLOCK_CONFIG(lfclk, ARRAY_SIZE(clock_options)) clk_cfg; @@ -161,7 +148,7 @@ static int lfclk_resolve_spec_to_idx(const struct device *dev, ? dev_data->max_accuracy : req_spec->accuracy; - for (int i = dev_data->clock_options_cnt - 1; i >= 0; --i) { + for (int i = 0; i < dev_data->clock_options_cnt; i++) { /* Iterate to a more power hungry and accurate clock source * If the requested accuracy is higher (lower ppm) than what * the clock source can provide. @@ -331,15 +318,17 @@ static int api_get_rate_lfclk(const struct device *dev, static int lfclk_init(const struct device *dev) { struct lfclk_dev_data *dev_data = dev->data; - nrf_bicr_lfosc_mode_t lfosc_mode; nrfs_err_t res; + int ret; + nrf_bicr_lfosc_mode_t lfosc_mode; + struct clock_options *clock_option; res = nrfs_clock_init(clock_evt_handler); if (res != NRFS_SUCCESS) { return -EIO; } - dev_data->clock_options_cnt = LFCLK_DEF_OPTS; + dev_data->clock_options_cnt = 0; lfosc_mode = nrf_bicr_lfosc_mode_get(BICR); @@ -347,8 +336,6 @@ static int lfclk_init(const struct device *dev) lfosc_mode == NRF_BICR_LFOSC_MODE_DISABLED) { dev_data->max_accuracy = LFCLK_HFXO_ACCURACY; } else { - int ret; - ret = lfosc_get_accuracy(&dev_data->max_accuracy); if (ret < 0) { LOG_ERR("LFOSC enabled with invalid accuracy"); @@ -357,34 +344,41 @@ static int lfclk_init(const struct device *dev) switch (lfosc_mode) { case NRF_BICR_LFOSC_MODE_CRYSTAL: - clock_options[LFCLK_MAX_OPTS - 1].accuracy = dev_data->max_accuracy; - clock_options[LFCLK_MAX_OPTS - 1].precision = 0; - clock_options[LFCLK_MAX_OPTS - 1].src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE; - - clock_options[LFCLK_MAX_OPTS - 2].accuracy = dev_data->max_accuracy; - clock_options[LFCLK_MAX_OPTS - 2].precision = 1; - clock_options[LFCLK_MAX_OPTS - 2].src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE_HP; - - dev_data->clock_options_cnt += 2; + clock_option = &clock_options[dev_data->clock_options_cnt]; + clock_option->accuracy = dev_data->max_accuracy; + clock_option->precision = 0; + clock_option->src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE; + dev_data->clock_options_cnt++; + + clock_option = &clock_options[dev_data->clock_options_cnt]; + clock_option->accuracy = dev_data->max_accuracy; + clock_option->precision = 1; + clock_option->src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE_HP; + dev_data->clock_options_cnt++; break; - case NRF_BICR_LFOSC_MODE_EXTSINE: - clock_options[LFCLK_MAX_OPTS - 1].accuracy = dev_data->max_accuracy; - clock_options[LFCLK_MAX_OPTS - 1].precision = 0; - clock_options[LFCLK_MAX_OPTS - 1].src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE; - clock_options[LFCLK_MAX_OPTS - 2].accuracy = dev_data->max_accuracy; - clock_options[LFCLK_MAX_OPTS - 2].precision = 1; - clock_options[LFCLK_MAX_OPTS - 2].src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE_HP; - - dev_data->clock_options_cnt += 2; + case NRF_BICR_LFOSC_MODE_EXTSINE: + clock_option = &clock_options[dev_data->clock_options_cnt]; + clock_option->accuracy = dev_data->max_accuracy; + clock_option->precision = 0; + clock_option->src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE; + dev_data->clock_options_cnt++; + + clock_option = &clock_options[dev_data->clock_options_cnt]; + clock_option->accuracy = dev_data->max_accuracy; + clock_option->precision = 1; + clock_option->src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE_HP; + dev_data->clock_options_cnt++; break; - case NRF_BICR_LFOSC_MODE_EXTSQUARE: - clock_options[LFCLK_MAX_OPTS - 2].accuracy = dev_data->max_accuracy; - clock_options[LFCLK_MAX_OPTS - 2].precision = 0; - clock_options[LFCLK_MAX_OPTS - 2].src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SQUARE; - dev_data->clock_options_cnt += 1; + case NRF_BICR_LFOSC_MODE_EXTSQUARE: + clock_option = &clock_options[dev_data->clock_options_cnt]; + clock_option->accuracy = dev_data->max_accuracy; + clock_option->precision = 0; + clock_option->src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SQUARE; + dev_data->clock_options_cnt++; break; + default: LOG_ERR("Unexpected LFOSC mode"); return -EINVAL; @@ -398,6 +392,18 @@ static int lfclk_init(const struct device *dev) } } + clock_option = &clock_options[dev_data->clock_options_cnt]; + clock_option->accuracy = LFCLK_LFRC_ACCURACY; + clock_option->precision = 0; + clock_option->src = NRFS_CLOCK_SRC_LFCLK_LFRC; + dev_data->clock_options_cnt++; + + clock_option = &clock_options[dev_data->clock_options_cnt]; + clock_option->accuracy = LFCLK_HFXO_ACCURACY; + clock_option->precision = 1; + clock_option->src = NRFS_CLOCK_SRC_LFCLK_SYNTH; + dev_data->clock_options_cnt++; + dev_data->hfxo_startup_time_us = nrf_bicr_hfxo_startup_time_us_get(BICR); if (dev_data->hfxo_startup_time_us == NRF_BICR_HFXO_STARTUP_TIME_UNCONFIGURED) { LOG_ERR("BICR HFXO startup time invalid"); diff --git a/drivers/comparator/comparator_nrf_comp.c b/drivers/comparator/comparator_nrf_comp.c index 311a864303bf..7178c51675d8 100644 --- a/drivers/comparator/comparator_nrf_comp.c +++ b/drivers/comparator/comparator_nrf_comp.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -19,8 +20,7 @@ #define SHIM_NRF_COMP_DT_INST_REFSEL_IS_AREF(inst) \ DT_INST_ENUM_HAS_VALUE(inst, refsel, aref) -#define SHIM_NRF_COMP_DT_INST_EXTREFSEL(inst) \ - _CONCAT(COMP_NRF_COMP_EXTREFSEL_, DT_INST_STRING_TOKEN(inst, extrefsel)) +#define SHIM_NRF_COMP_DT_INST_EXTREFSEL(inst) DT_INST_PROP(inst, extrefsel) #define SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(inst) \ DT_INST_ENUM_HAS_VALUE(inst, main_mode, se) @@ -43,8 +43,7 @@ #define SHIM_NRF_COMP_DT_INST_ISOURCE(inst) \ _CONCAT(COMP_NRF_COMP_ISOURCE_, DT_INST_STRING_TOKEN(inst, isource)) -#define SHIM_NRF_COMP_DT_INST_PSEL(inst) \ - _CONCAT(COMP_NRF_COMP_PSEL_, DT_INST_STRING_TOKEN(inst, psel)) +#define SHIM_NRF_COMP_DT_INST_PSEL(inst) DT_INST_PROP(inst, psel) #if defined(COMP_HYST_HYST_Hyst40mV) #define NRF_COMP_HYST_ENABLED NRF_COMP_HYST_40MV @@ -73,35 +72,50 @@ BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_TH_DOWN(0) < 64); BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_TH_UP(0) < 64); #endif -#if NRF_COMP_HAS_AIN_AS_PIN -BUILD_ASSERT((COMP_NRF_COMP_PSEL_AIN0 == 0)); -BUILD_ASSERT((COMP_NRF_COMP_PSEL_AIN7 == 7)); -BUILD_ASSERT((COMP_NRF_COMP_EXTREFSEL_AIN0 == 0)); -BUILD_ASSERT((COMP_NRF_COMP_EXTREFSEL_AIN7 == 7)); +#if (NRF_COMP_HAS_AIN_AS_PIN) +BUILD_ASSERT(NRF_COMP_AIN0 == 0); +BUILD_ASSERT(NRF_COMP_AIN7 == 7); #else -#ifndef COMP_PSEL_PSEL_AnalogInput4 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN4); +BUILD_ASSERT((NRF_COMP_AIN0 == NRF_COMP_INPUT_0) && + (NRF_COMP_AIN1 == NRF_COMP_INPUT_1) && + (NRF_COMP_AIN2 == NRF_COMP_INPUT_2) && + (NRF_COMP_AIN3 == NRF_COMP_INPUT_3) && +#if defined(COMP_PSEL_PSEL_AnalogInput4) + (NRF_COMP_AIN4 == NRF_COMP_INPUT_4) && #endif - -#ifndef COMP_PSEL_PSEL_AnalogInput5 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN5); +#if defined(COMP_PSEL_PSEL_AnalogInput5) + (NRF_COMP_AIN5 == NRF_COMP_INPUT_5) && #endif - -#ifndef COMP_PSEL_PSEL_AnalogInput6 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN6); +#if defined(COMP_PSEL_PSEL_AnalogInput6) + (NRF_COMP_AIN6 == NRF_COMP_INPUT_6) && #endif - -#ifndef COMP_PSEL_PSEL_AnalogInput7 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_AIN7); +#if defined(COMP_PSEL_PSEL_AnalogInput7) + (NRF_COMP_AIN7 == NRF_COMP_INPUT_7) && #endif + (NRF_COMP_AIN0 == NRF_COMP_EXT_REF_0) && + (NRF_COMP_AIN1 == NRF_COMP_EXT_REF_1) && + (NRF_COMP_AIN2 == NRF_COMP_EXT_REF_2) && + (NRF_COMP_AIN3 == NRF_COMP_EXT_REF_3) && +#if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference4) + (NRF_COMP_AIN4 == NRF_COMP_EXT_REF_4) && #endif - -#ifndef COMP_PSEL_PSEL_VddDiv2 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_VDD_DIV2); +#if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference5) + (NRF_COMP_AIN5 == NRF_COMP_EXT_REF_5) && #endif - -#ifndef COMP_PSEL_PSEL_VddhDiv5 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_PSEL(0) != COMP_NRF_COMP_PSEL_VDDH_DIV5); +#if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference6) + (NRF_COMP_AIN6 == NRF_COMP_EXT_REF_6) && +#endif +#if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference7) + (NRF_COMP_AIN7 == NRF_COMP_EXT_REF_7) && +#endif +#if defined(COMP_PSEL_PSEL_VddDiv2) + (NRF_COMP_VDD_DIV2 == NRF_COMP_VDD_DIV2) && +#endif +#if defined(COMP_PSEL_PSEL_VddhDiv5) + (NRF_COMP_VDDH_DIV5 == NRF_COMP_VDDH_DIV5) && +#endif + 1, + "Definitions from nrf-comp.h do not match those from HAL"); #endif #ifndef COMP_MODE_SP_Normal @@ -122,24 +136,6 @@ BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_ISOURCE(0) != COMP_NRF_COMP_ISOURCE_10UA); #endif #endif -#if SHIM_NRF_COMP_DT_INST_REFSEL_IS_AREF(0) -#ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference4 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN4); -#endif - -#ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference5 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN5); -#endif - -#ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference6 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN6); -#endif - -#ifndef COMP_EXTREFSEL_EXTREFSEL_AnalogReference7 -BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_EXTREFSEL(0) != COMP_NRF_COMP_EXTREFSEL_AIN7); -#endif -#endif - #if SHIM_NRF_COMP_DT_INST_MAIN_MODE_IS_SE(0) #ifndef COMP_REFSEL_REFSEL_Int1V8 BUILD_ASSERT(SHIM_NRF_COMP_DT_INST_REFSEL(0) != COMP_NRF_COMP_REFSEL_INT_1V8); @@ -246,69 +242,74 @@ static int shim_nrf_comp_pm_callback(const struct device *dev, enum pm_device_ac } #if (NRF_COMP_HAS_AIN_AS_PIN) -static int shim_nrf_comp_psel_to_nrf(enum comp_nrf_comp_psel shim, +static int shim_nrf_comp_psel_to_nrf(uint8_t shim, nrf_comp_input_t *nrf) { if (shim >= ARRAY_SIZE(shim_nrf_comp_ain_map)) { return -EINVAL; } - *nrf = shim_nrf_comp_ain_map[(uint32_t)shim]; + *nrf = shim_nrf_comp_ain_map[shim]; + +#if NRF_GPIO_HAS_RETENTION_SETCLEAR + nrf_gpio_pin_retain_disable(shim_nrf_comp_ain_map[shim]); +#endif + return 0; } #else -static int shim_nrf_comp_psel_to_nrf(enum comp_nrf_comp_psel shim, +static int shim_nrf_comp_psel_to_nrf(uint8_t shim, nrf_comp_input_t *nrf) { switch (shim) { - case COMP_NRF_COMP_PSEL_AIN0: + case NRF_COMP_AIN0: *nrf = NRF_COMP_INPUT_0; break; - case COMP_NRF_COMP_PSEL_AIN1: + case NRF_COMP_AIN1: *nrf = NRF_COMP_INPUT_1; break; - case COMP_NRF_COMP_PSEL_AIN2: + case NRF_COMP_AIN2: *nrf = NRF_COMP_INPUT_2; break; - case COMP_NRF_COMP_PSEL_AIN3: + case NRF_COMP_AIN3: *nrf = NRF_COMP_INPUT_3; break; #if defined(COMP_PSEL_PSEL_AnalogInput4) - case COMP_NRF_COMP_PSEL_AIN4: + case NRF_COMP_AIN4: *nrf = NRF_COMP_INPUT_4; break; #endif #if defined(COMP_PSEL_PSEL_AnalogInput5) - case COMP_NRF_COMP_PSEL_AIN5: + case NRF_COMP_AIN5: *nrf = NRF_COMP_INPUT_5; break; #endif #if defined(COMP_PSEL_PSEL_AnalogInput6) - case COMP_NRF_COMP_PSEL_AIN6: + case NRF_COMP_AIN6: *nrf = NRF_COMP_INPUT_6; break; #endif #if defined(COMP_PSEL_PSEL_AnalogInput7) - case COMP_NRF_COMP_PSEL_AIN7: + case NRF_COMP_AIN7: *nrf = NRF_COMP_INPUT_7; break; #endif #if defined(COMP_PSEL_PSEL_VddDiv2) - case COMP_NRF_COMP_PSEL_VDD_DIV2: + case NRF_COMP_AIN_VDD_DIV2: *nrf = NRF_COMP_VDD_DIV2; break; #endif #if defined(COMP_PSEL_PSEL_VddhDiv5) - case COMP_NRF_COMP_PSEL_VDDH_DIV5: + case NRF_COMP_AIN_VDDH_DIV5: *nrf = NRF_COMP_VDDH_DIV5; break; #endif @@ -382,57 +383,57 @@ static int shim_nrf_comp_isource_to_nrf(enum comp_nrf_comp_isource shim, #endif #if (NRF_COMP_HAS_AIN_AS_PIN) -static int shim_nrf_comp_extrefsel_to_nrf(enum comp_nrf_comp_extrefsel shim, +static int shim_nrf_comp_extrefsel_to_nrf(uint8_t shim, nrf_comp_ext_ref_t *nrf) { if (shim >= ARRAY_SIZE(shim_nrf_comp_ain_map)) { return -EINVAL; } - *nrf = shim_nrf_comp_ain_map[(uint32_t)shim]; + *nrf = shim_nrf_comp_ain_map[shim]; return 0; } #else -static int shim_nrf_comp_extrefsel_to_nrf(enum comp_nrf_comp_extrefsel shim, +static int shim_nrf_comp_extrefsel_to_nrf(uint8_t shim, nrf_comp_ext_ref_t *nrf) { switch (shim) { - case COMP_NRF_COMP_EXTREFSEL_AIN0: + case NRF_COMP_AIN0: *nrf = NRF_COMP_EXT_REF_0; break; - case COMP_NRF_COMP_EXTREFSEL_AIN1: + case NRF_COMP_AIN1: *nrf = NRF_COMP_EXT_REF_1; break; - case COMP_NRF_COMP_EXTREFSEL_AIN2: + case NRF_COMP_AIN2: *nrf = NRF_COMP_EXT_REF_2; break; - case COMP_NRF_COMP_EXTREFSEL_AIN3: + case NRF_COMP_AIN3: *nrf = NRF_COMP_EXT_REF_3; break; #if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference4) - case COMP_NRF_COMP_EXTREFSEL_AIN4: + case NRF_COMP_AIN4: *nrf = NRF_COMP_EXT_REF_4; break; #endif #if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference5) - case COMP_NRF_COMP_EXTREFSEL_AIN5: + case NRF_COMP_AIN5: *nrf = NRF_COMP_EXT_REF_5; break; #endif #if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference6) - case COMP_NRF_COMP_EXTREFSEL_AIN6: + case NRF_COMP_AIN6: *nrf = NRF_COMP_EXT_REF_6; break; #endif #if defined(COMP_EXTREFSEL_EXTREFSEL_AnalogReference7) - case COMP_NRF_COMP_EXTREFSEL_AIN7: + case NRF_COMP_AIN7: *nrf = NRF_COMP_EXT_REF_7; break; #endif diff --git a/drivers/comparator/comparator_nrf_lpcomp.c b/drivers/comparator/comparator_nrf_lpcomp.c index 623c7adacd42..dbd58d342360 100644 --- a/drivers/comparator/comparator_nrf_lpcomp.c +++ b/drivers/comparator/comparator_nrf_lpcomp.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -21,14 +22,12 @@ #define SHIM_NRF_LPCOMP_DT_INST_REFSEL_IS_AREF(inst) \ DT_INST_ENUM_HAS_VALUE(inst, refsel, aref) -#define SHIM_NRF_LPCOMP_DT_INST_EXTREFSEL(inst) \ - _CONCAT(COMP_NRF_LPCOMP_EXTREFSEL_, DT_INST_STRING_TOKEN(inst, extrefsel)) +#define SHIM_NRF_LPCOMP_DT_INST_EXTREFSEL(inst) DT_INST_PROP(inst, extrefsel) #define SHIM_NRF_LPCOMP_DT_INST_ENABLE_HYST(inst) \ DT_INST_PROP(inst, enable_hyst) -#define SHIM_NRF_LPCOMP_DT_INST_PSEL(inst) \ - _CONCAT(COMP_NRF_LPCOMP_PSEL_, DT_INST_STRING_TOKEN(inst, psel)) +#define SHIM_NRF_LPCOMP_DT_INST_PSEL(inst) DT_INST_PROP(inst, psel) struct shim_nrf_lpcomp_data { nrfx_lpcomp_config_t config; @@ -40,10 +39,20 @@ struct shim_nrf_lpcomp_data { }; #if (NRF_LPCOMP_HAS_AIN_AS_PIN) -BUILD_ASSERT(COMP_NRF_LPCOMP_PSEL_AIN0 == 0); -BUILD_ASSERT(COMP_NRF_LPCOMP_PSEL_AIN7 == 7); -BUILD_ASSERT(COMP_NRF_LPCOMP_EXTREFSEL_AIN0 == 0); -BUILD_ASSERT(COMP_NRF_LPCOMP_EXTREFSEL_AIN1 == 1); +BUILD_ASSERT(NRF_COMP_AIN0 == 0); +BUILD_ASSERT(NRF_COMP_AIN7 == 7); +#else +BUILD_ASSERT((NRF_COMP_AIN0 == NRF_LPCOMP_INPUT_0) && + (NRF_COMP_AIN1 == NRF_LPCOMP_INPUT_1) && + (NRF_COMP_AIN2 == NRF_LPCOMP_INPUT_2) && + (NRF_COMP_AIN3 == NRF_LPCOMP_INPUT_3) && + (NRF_COMP_AIN4 == NRF_LPCOMP_INPUT_4) && + (NRF_COMP_AIN5 == NRF_LPCOMP_INPUT_5) && + (NRF_COMP_AIN6 == NRF_LPCOMP_INPUT_6) && + (NRF_COMP_AIN7 == NRF_LPCOMP_INPUT_7) && + (NRF_COMP_AIN0 == NRF_LPCOMP_EXT_REF_REF0) && + (NRF_COMP_AIN1 == NRF_LPCOMP_EXT_REF_REF1), + "Definitions from nrf-comp.h do not match those from HAL"); #endif #if (LPCOMP_REFSEL_RESOLUTION == 8) @@ -126,50 +135,55 @@ static int shim_nrf_lpcomp_pm_callback(const struct device *dev, enum pm_device_ } #if (NRF_LPCOMP_HAS_AIN_AS_PIN) -static int shim_nrf_lpcomp_psel_to_nrf(enum comp_nrf_lpcomp_psel shim, +static int shim_nrf_lpcomp_psel_to_nrf(uint8_t shim, nrf_lpcomp_input_t *nrf) { if (shim >= ARRAY_SIZE(shim_nrf_comp_ain_map)) { return -EINVAL; } - *nrf = shim_nrf_comp_ain_map[(uint32_t)shim]; + *nrf = shim_nrf_comp_ain_map[shim]; + +#if NRF_GPIO_HAS_RETENTION_SETCLEAR + nrf_gpio_pin_retain_disable(shim_nrf_comp_ain_map[shim]); +#endif + return 0; } #else -static int shim_nrf_lpcomp_psel_to_nrf(enum comp_nrf_lpcomp_psel shim, +static int shim_nrf_lpcomp_psel_to_nrf(uint8_t shim, nrf_lpcomp_input_t *nrf) { switch (shim) { - case COMP_NRF_LPCOMP_PSEL_AIN0: + case NRF_COMP_AIN0: *nrf = NRF_LPCOMP_INPUT_0; break; - case COMP_NRF_LPCOMP_PSEL_AIN1: + case NRF_COMP_AIN1: *nrf = NRF_LPCOMP_INPUT_1; break; - case COMP_NRF_LPCOMP_PSEL_AIN2: + case NRF_COMP_AIN2: *nrf = NRF_LPCOMP_INPUT_2; break; - case COMP_NRF_LPCOMP_PSEL_AIN3: + case NRF_COMP_AIN3: *nrf = NRF_LPCOMP_INPUT_3; break; - case COMP_NRF_LPCOMP_PSEL_AIN4: + case NRF_COMP_AIN4: *nrf = NRF_LPCOMP_INPUT_4; break; - case COMP_NRF_LPCOMP_PSEL_AIN5: + case NRF_COMP_AIN5: *nrf = NRF_LPCOMP_INPUT_5; break; - case COMP_NRF_LPCOMP_PSEL_AIN6: + case NRF_COMP_AIN6: *nrf = NRF_LPCOMP_INPUT_6; break; - case COMP_NRF_LPCOMP_PSEL_AIN7: + case NRF_COMP_AIN7: *nrf = NRF_LPCOMP_INPUT_7; break; @@ -182,7 +196,7 @@ static int shim_nrf_lpcomp_psel_to_nrf(enum comp_nrf_lpcomp_psel shim, #endif #if (NRF_LPCOMP_HAS_AIN_AS_PIN) -static int shim_nrf_lpcomp_extrefsel_to_nrf(enum comp_nrf_lpcomp_extrefsel shim, +static int shim_nrf_lpcomp_extrefsel_to_nrf(uint8_t shim, nrf_lpcomp_ext_ref_t *nrf) { if (shim >= ARRAY_SIZE(shim_nrf_comp_ain_map)) { @@ -193,15 +207,15 @@ static int shim_nrf_lpcomp_extrefsel_to_nrf(enum comp_nrf_lpcomp_extrefsel shim, return 0; } #else -static int shim_nrf_lpcomp_extrefsel_to_nrf(enum comp_nrf_lpcomp_extrefsel shim, +static int shim_nrf_lpcomp_extrefsel_to_nrf(uint8_t shim, nrf_lpcomp_ext_ref_t *nrf) { switch (shim) { - case COMP_NRF_LPCOMP_EXTREFSEL_AIN0: + case NRF_COMP_AIN0: *nrf = NRF_LPCOMP_EXT_REF_REF0; break; - case COMP_NRF_LPCOMP_EXTREFSEL_AIN1: + case NRF_COMP_AIN1: *nrf = NRF_LPCOMP_EXT_REF_REF1; break; diff --git a/drivers/counter/counter_nrfx_timer.c b/drivers/counter/counter_nrfx_timer.c index 26fa49b1aeed..1a614b391c06 100644 --- a/drivers/counter/counter_nrfx_timer.c +++ b/drivers/counter/counter_nrfx_timer.c @@ -5,7 +5,6 @@ */ #include #include -#include #include #include #include @@ -35,21 +34,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL); #define MAYBE_CONST_CONFIG const #endif -#if NRF_DT_INST_ANY_IS_FAST && CONFIG_CLOCK_CONTROL -#define COUNTER_IS_FAST(idx) NRF_DT_INST_IS_FAST(idx) -#define COUNTER_ANY_FAST -#else -#define COUNTER_IS_FAST(idx) 0 -#endif - struct counter_nrfx_data { counter_top_callback_t top_cb; void *top_user_data; uint32_t guard_period; atomic_t cc_int_pending; -#ifdef COUNTER_ANY_FAST - atomic_t active; -#endif }; struct counter_nrfx_ch_data { @@ -61,10 +50,6 @@ struct counter_nrfx_config { struct counter_config_info info; struct counter_nrfx_ch_data *ch_data; NRF_TIMER_Type *timer; -#ifdef COUNTER_ANY_FAST - const struct device *clk_dev; - struct nrf_clock_spec clk_spec; -#endif LOG_INSTANCE_PTR_DECLARE(log); }; @@ -78,18 +63,6 @@ static int start(const struct device *dev) { const struct counter_nrfx_config *config = dev->config; -#ifdef COUNTER_ANY_FAST - struct counter_nrfx_data *data = dev->data; - - if (config->clk_dev && atomic_cas(&data->active, 0, 1)) { - int err; - - err = nrf_clock_control_request_sync(config->clk_dev, &config->clk_spec, K_FOREVER); - if (err < 0) { - return err; - } - } -#endif nrf_timer_task_trigger(config->timer, NRF_TIMER_TASK_START); return 0; @@ -106,19 +79,6 @@ static int stop(const struct device *dev) nrf_timer_task_trigger(config->timer, NRF_TIMER_TASK_CLEAR); #endif -#ifdef COUNTER_ANY_FAST - struct counter_nrfx_data *data = dev->data; - - if (config->clk_dev && atomic_cas(&data->active, 1, 0)) { - int err; - - err = nrf_clock_control_release(config->clk_dev, &config->clk_spec); - if (err < 0) { - return err; - } - } -#endif - return 0; } @@ -459,20 +419,6 @@ static DEVICE_API(counter, counter_nrfx_driver_api) = { .set_guard_period = set_guard_period, }; -/* Get initialization level of an instance. Instances that requires clock control - * which is using nrfs (IPC) are initialized later. - */ -#define TIMER_INIT_LEVEL(idx) \ - COND_CODE_1(COUNTER_IS_FAST(idx), (POST_KERNEL), (PRE_KERNEL_1)) - -/* Get initialization priority of an instance. Instances that requires clock control - * which is using nrfs (IPC) are initialized later. - */ -#define TIMER_INIT_PRIO(idx) \ - COND_CODE_1(COUNTER_IS_FAST(idx), \ - (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \ - (CONFIG_COUNTER_INIT_PRIORITY)) - /* * Device instantiation is done with node labels due to HAL API * requirements. In particular, TIMERx_MAX_SIZE values from HALs @@ -525,14 +471,6 @@ static DEVICE_API(counter, counter_nrfx_driver_api) = { }, \ .ch_data = counter##idx##_ch_data, \ .timer = (NRF_TIMER_Type *)DT_INST_REG_ADDR(idx), \ - IF_ENABLED(COUNTER_IS_FAST(idx), \ - (.clk_dev = DEVICE_DT_GET_OR_NULL(DT_CLOCKS_CTLR(DT_DRV_INST(idx))), \ - .clk_spec = { \ - .frequency = NRF_PERIPH_GET_FREQUENCY(DT_DRV_INST(idx)), \ - .accuracy = 0, \ - .precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT, \ - }, \ - )) \ LOG_INSTANCE_PTR_INIT(log, LOG_MODULE_NAME, idx) \ }; \ DEVICE_DT_INST_DEFINE(idx, \ @@ -540,7 +478,7 @@ static DEVICE_API(counter, counter_nrfx_driver_api) = { NULL, \ &counter_##idx##_data, \ &nrfx_counter_##idx##_config.info, \ - TIMER_INIT_LEVEL(idx), TIMER_INIT_PRIO(idx), \ + PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \ &counter_nrfx_driver_api); DT_INST_FOREACH_STATUS_OKAY(COUNTER_NRFX_TIMER_DEVICE) diff --git a/drivers/debug/CMakeLists.txt b/drivers/debug/CMakeLists.txt index 54ca9f71694e..29763be07ec1 100644 --- a/drivers/debug/CMakeLists.txt +++ b/drivers/debug/CMakeLists.txt @@ -4,5 +4,7 @@ zephyr_library() # zephyr-keep-sorted-start +zephyr_library_sources_ifdef(CONFIG_DEBUG_CORESIGHT_NRF debug_coresight_nrf.c) +zephyr_library_sources_ifdef(CONFIG_DEBUG_NRF_ETR debug_nrf_etr.c) zephyr_library_sources_ifdef(CONFIG_DEBUG_SILABS_PTI debug_silabs_pti.c) # zephyr-keep-sorted-stop diff --git a/drivers/debug/Kconfig b/drivers/debug/Kconfig index 68c23fdf1243..b38c5206f3cb 100644 --- a/drivers/debug/Kconfig +++ b/drivers/debug/Kconfig @@ -15,6 +15,7 @@ config DEBUG_DRIVER_INIT_PRIORITY Debug drivers initialization priority. # zephyr-keep-sorted-start +source "drivers/debug/Kconfig.nrf" source "drivers/debug/Kconfig.silabs" # zephyr-keep-sorted-stop diff --git a/drivers/misc/coresight/Kconfig b/drivers/debug/Kconfig.nrf similarity index 51% rename from drivers/misc/coresight/Kconfig rename to drivers/debug/Kconfig.nrf index 997d0c23c0a5..030e9885a06d 100644 --- a/drivers/misc/coresight/Kconfig +++ b/drivers/debug/Kconfig.nrf @@ -3,7 +3,7 @@ DT_COMPAT_NORDIC_NRF_TBM := nordic,nrf-tbm -config NRF_ETR +config DEBUG_NRF_ETR bool "Coresight ETR handler (with Nordic TBM)" depends on $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_TBM)) select NRFX_TBM @@ -14,9 +14,9 @@ config NRF_ETR data). Busyness is tracked using TBM (Trace Buffer Monitor) peripheral which is specific to Nordic Semiconductor SoCs. -if NRF_ETR +if DEBUG_NRF_ETR -config NRF_ETR_DECODE +config DEBUG_NRF_ETR_DECODE bool "Decode ETR content" default y if LOG_FRONTEND_STMESP_FSC select MIPI_STP_DECODER @@ -29,14 +29,14 @@ config NRF_ETR_DECODE In this mode, log messages stored by Coresight STM logging frontends are decoded and printed in the human readable form. -config NRF_ETR_DECODE_DROP_PERIOD +config DEBUG_NRF_ETR_DECODE_DROP_PERIOD int "Period of dropped messages notification" default 5000 help Period (in milliseconds) how often it is checked if any dropped messages have occurred. -config NRF_ETR_DEBUG +config DEBUG_NRF_ETR_DEBUG bool "Debug mode" depends on !LOG_PRINTK select MIPI_STP_DECODER @@ -44,18 +44,18 @@ config NRF_ETR_DEBUG help In debug mode STPv2 decoded data is printed. -config NRF_ETR_STACK_SIZE +config DEBUG_NRF_ETR_STACK_SIZE int "ETR thread stack size" - default 2048 if NRF_ETR_DECODE || NRF_ETR_DEBUG + default 2048 if DEBUG_NRF_ETR_DECODE || DEBUG_NRF_ETR_DEBUG default 1024 -config NRF_ETR_BACKOFF +config DEBUG_NRF_ETR_BACKOFF int "Thread backoff time (ms)" default 10 help Determines how often attempt to dump the data is performed. -config NRF_ETR_FLUSH_TIMEOUT +config DEBUG_NRF_ETR_FLUSH_TIMEOUT int "Backoff time during flushing (ms)" default 100 help @@ -63,10 +63,10 @@ config NRF_ETR_FLUSH_TIMEOUT there is still a pending ETR data. This option specifies how often thread is waking up to check. Given in milliseconds. -config NRF_ETR_SYNC_PERIOD +config DEBUG_NRF_ETR_SYNC_PERIOD int "Period of custom synchronization frame" - default 0 if NRF_ETR_DECODE - default 0 if NRF_ETR_DEBUG + default 0 if DEBUG_NRF_ETR_DECODE + default 0 if DEBUG_NRF_ETR_DEBUG default 16 help To help find the synchronization when decoding the ETR content @@ -74,25 +74,25 @@ config NRF_ETR_SYNC_PERIOD sent on regular intervals. This frame is sent between Coresight formatter frames. Use 0 to disable. -config NRF_ETR_SHELL +config DEBUG_NRF_ETR_SHELL bool "Use shell" select UART_ASYNC_API select UART_ASYNC_RX_HELPER select SHELL_LOG_BACKEND_CUSTOM - depends on NRF_ETR_DECODE + depends on DEBUG_NRF_ETR_DECODE default y if SHELL help Enable shell with Coresight STM logging support. -if NRF_ETR_SHELL +if DEBUG_NRF_ETR_SHELL -config NRF_ETR_SHELL_PROMPT +config DEBUG_NRF_ETR_SHELL_PROMPT string "Displayed prompt name" default "uart:~$ " help Displayed prompt name for UART shell with Coresight STM logging. -config NRF_ETR_SHELL_ASYNC_RX_BUFFER_SIZE +config DEBUG_NRF_ETR_SHELL_ASYNC_RX_BUFFER_SIZE int "Size of the RX buffer" default 16 help @@ -101,13 +101,78 @@ config NRF_ETR_SHELL_ASYNC_RX_BUFFER_SIZE slow and may need to be increased if long messages are pasted directly to the shell prompt. -config NRF_ETR_SHELL_ASYNC_RX_BUFFER_COUNT +config DEBUG_NRF_ETR_SHELL_ASYNC_RX_BUFFER_COUNT int "Number of RX buffers" default 4 range 2 64 help Number of RX buffers. -endif # NRF_ETR_SHELL +endif # DEBUG_NRF_ETR_SHELL -endif # NRF_ETR +endif # DEBUG_NRF_ETR + +menuconfig DEBUG_CORESIGHT_NRF + bool "Coresight Trace support" + default y + depends on DT_HAS_NORDIC_CORESIGHT_NRF_ENABLED + select PINCTRL + select NRF_IRONSIDE_TDD_SERVICE + help + Support CoreSight peripherals in Test and Debug Domain for ARM + CoreSight System Trace Macrocell (STM) trace support. + +if DEBUG_CORESIGHT_NRF + +config DEBUG_CORESIGHT_NRF_ATB_TRACE_ID_STM_GLOBAL + def_hex 0x40 + help + Global trace ID used by STM. + +config DEBUG_CORESIGHT_NRF_STM_SYNC_BYTE_COUNT + int "STM: Emit synhronization packet every N bytes" + range 0 4095 + default 512 + +config DEBUG_CORESIGHT_NRF_STM_HWEVENTS + bool "STM: Enable hardware events" + help + Enable the output of hardware events in STM. + +config DEBUG_CORESIGHT_NRF_TPIU_FFCR_TRIG + bool "TPIU: Use flush request trigger" + default y + help + Use CTI channel 1 for triggering flush request in TPIU. + +config DEBUG_CORESIGHT_NRF_TPIU_SYNC_FRAME_COUNT + int "TPIU: Emit synchronisation packet every N frames" + default 8 + +config DEBUG_CORESIGHT_NRF_TPIU_PORTSIZE + int "TPIU: Size of the current TPIU port in bits" + range 1 32 + default 4 + +config DEBUG_CORESIGHT_NRF_ATBFUNNEL_HOLD_TIME + int "ATBFUNNEL: Hold time for the transaction" + range 1 15 + default 4 + help + Number of transactions that are output on the funnel master port from the + same slave. + +config DEBUG_CORESIGHT_NRF_TSGEN_CLK_DIV + int + default 8 + help + Clock division factor for generating trace timestamps. The timestamp + counter should not be slower than 10% of the fastest processor clock + frequency in the system, therefore its clock speed is divided by + eight. + +module = DEBUG_CORESIGHT_NRF +module-str = CoreSight Trace +source "subsys/logging/Kconfig.template.log_config" + +endif # DEBUG_CORESIGHT_NRF diff --git a/drivers/debug/coresight_arm.h b/drivers/debug/coresight_arm.h new file mode 100644 index 000000000000..b0c5da3e92d0 --- /dev/null +++ b/drivers/debug/coresight_arm.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef CORESIGHT_ARM_H_ +#define CORESIGHT_ARM_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @brief Generic ARM CoreSight Hardware Abstraction Layer + * + * This HAL provides generic register definitions and utility functions for ARM CoreSight + * peripherals. Platform-specific drivers should provide base addresses and use these + * generic definitions for register access. + */ + +/* Common CoreSight unlock key as defined by ARM architecture */ +#define CORESIGHT_UNLOCK_KEY (0xC5ACCE55UL) + +/* CoreSight register offsets */ + +/* Common CoreSight peripheral register offsets (found at the end of all CoreSight peripherals) */ +#define CORESIGHT_CLAIMSET_OFFSET (0xFA0UL) /* Claim Tag Set Register */ +#define CORESIGHT_CLAIMCLR_OFFSET (0xFA4UL) /* Claim Tag Clear Register */ +#define CORESIGHT_LAR_OFFSET (0xFB0UL) /* Lock Access Register */ +#define CORESIGHT_LSR_OFFSET (0xFB4UL) /* Lock Status Register */ + +/* ATB Funnel register offsets */ +#define ATBFUNNEL_CTRLREG_OFFSET (0x000UL) /* Control Register */ + +/* ATB Replicator register offsets */ +#define ATBREPLICATOR_IDFILTER0_OFFSET (0x000UL) /* ID Filter Register 0 */ +#define ATBREPLICATOR_IDFILTER1_OFFSET (0x004UL) /* ID Filter Register 1 */ + +/* ETR (Embedded Trace Router/TMC-ETR) register offsets */ +#define ETR_RSZ_OFFSET (0x004UL) /* RAM Size Register */ +#define ETR_RWP_OFFSET (0x018UL) /* RAM Write Pointer Register */ +#define ETR_CTL_OFFSET (0x020UL) /* Control Register */ +#define ETR_MODE_OFFSET (0x028UL) /* Mode Register */ +#define ETR_DBALO_OFFSET (0x118UL) /* Data Buffer Address Low Register */ +#define ETR_DBAHI_OFFSET (0x11CUL) /* Data Buffer Address High Register */ +#define ETR_FFCR_OFFSET (0x304UL) /* Formatter and Flush Control Register */ + +/* STM (System Trace Macrocell) register offsets */ +#define STM_STMHEER_OFFSET (0xD00UL) /* Hardware Event Enable Register */ +#define STM_STMHEMCR_OFFSET (0xD64UL) /* Hardware Event Master Control Register */ +#define STM_STMSPER_OFFSET (0xE00UL) /* Stimulus Port Enable Register */ +#define STM_STMTCSR_OFFSET (0xE80UL) /* Trace Control and Status Register */ +#define STM_STMTSFREQR_OFFSET (0xE8CUL) /* Timestamp Frequency Register */ +#define STM_STMSYNCR_OFFSET (0xE90UL) /* Synchronization Control Register */ +#define STM_STMAUXCR_OFFSET (0xE94UL) /* Auxiliary Control Register */ + +/* TPIU (Trace Port Interface Unit) register offsets */ +#define TPIU_CSPSR_OFFSET (0x004UL) /* Current Parallel Port Size Register */ +#define TPIU_FFCR_OFFSET (0x304UL) /* Formatter and Flush Control Register */ +#define TPIU_FSCR_OFFSET (0x308UL) /* Formatter Synchronization Counter Register */ + +/* CTI (Cross Trigger Interface) register offsets */ +#define CTI_CTICONTROL_OFFSET (0x000UL) /* CTI Control Register */ +#define CTI_CTIOUTEN0_OFFSET (0x0A0UL) /* CTI Trigger Output Enable Register 0 */ +#define CTI_CTIGATE_OFFSET (0x140UL) /* CTI Channel Gate Enable Register */ + +/* TSGEN (Timestamp Generator) register offsets */ +#define TSGEN_CNTCR_OFFSET (0x000UL) /* Counter Control Register */ +#define TSGEN_CNTFID0_OFFSET (0x020UL) /* Counter Frequency ID Register 0 */ + +/* Lock Status Register (LSR) bit fields */ +#define CORESIGHT_LSR_LOCKED_Pos (1UL) +#define CORESIGHT_LSR_LOCKED_Msk (0x1UL << CORESIGHT_LSR_LOCKED_Pos) +#define CORESIGHT_LSR_PRESENT_Pos (0UL) +#define CORESIGHT_LSR_PRESENT_Msk (0x1UL << CORESIGHT_LSR_PRESENT_Pos) + +/* STM Trace Control and Status Register (STMTCSR) bit fields */ +#define STM_STMTCSR_EN_Pos (0UL) +#define STM_STMTCSR_EN_Msk (0x1UL << STM_STMTCSR_EN_Pos) +#define STM_STMTCSR_TSEN_Pos (1UL) +#define STM_STMTCSR_TSEN_Msk (0x1UL << STM_STMTCSR_TSEN_Pos) +#define STM_STMTCSR_TRACEID_Pos (16UL) +#define STM_STMTCSR_TRACEID_Msk (0x7FUL << STM_STMTCSR_TRACEID_Pos) + +/* STM Hardware Event Master Control Register (STMHEMCR) bit fields */ +#define STM_STMHEMCR_EN_Pos (0UL) +#define STM_STMHEMCR_EN_Msk (0x1UL << STM_STMHEMCR_EN_Pos) + +/* STM Auxiliary Control Register (STMAUXCR) bit fields */ +#define STM_STMAUXCR_FIFOAF_Pos (0UL) +#define STM_STMAUXCR_FIFOAF_Msk (0x1UL << STM_STMAUXCR_FIFOAF_Pos) + +/* CTI Control Register (CTICONTROL) bit fields */ +#define CTI_CTICONTROL_GLBEN_Pos (0UL) +#define CTI_CTICONTROL_GLBEN_Msk (0x1UL << CTI_CTICONTROL_GLBEN_Pos) + +/* TPIU Formatter and Flush Control Register (FFCR) bit fields */ +#define TPIU_FFCR_ENFCONT_Pos (1UL) +#define TPIU_FFCR_ENFCONT_Msk (0x1UL << TPIU_FFCR_ENFCONT_Pos) +#define TPIU_FFCR_FONFLIN_Pos (4UL) +#define TPIU_FFCR_FONFLIN_Msk (0x1UL << TPIU_FFCR_FONFLIN_Pos) +#define TPIU_FFCR_ENFTC_Pos (0UL) +#define TPIU_FFCR_ENFTC_Msk (0x1UL << TPIU_FFCR_ENFTC_Pos) + +/* ETR Mode Register bit fields */ +#define ETR_MODE_MODE_Pos (0UL) +#define ETR_MODE_MODE_Msk (0x3UL << ETR_MODE_MODE_Pos) +#define ETR_MODE_MODE_CIRCULARBUF (0UL) /* Circular Buffer mode */ +#define ETR_MODE_MODE_SWFIFO1 (1UL) /* Software FIFO mode */ +#define ETR_MODE_MODE_HWFIFO (2UL) /* Hardware FIFO mode */ +#define ETR_MODE_MODE_SWFIFO2 (3UL) /* Software FIFO mode */ + +/* ETR Control Register bit fields */ +#define ETR_CTL_TRACECAPTEN_Pos (0UL) +#define ETR_CTL_TRACECAPTEN_Msk (0x1UL << ETR_CTL_TRACECAPTEN_Pos) + +/* ETR Formatter and Flush Control Register (FFCR) bit fields */ +#define ETR_FFCR_ENFT_Pos (0UL) +#define ETR_FFCR_ENFT_Msk (0x1UL << ETR_FFCR_ENFT_Pos) +#define ETR_FFCR_ENTI_Pos (1UL) +#define ETR_FFCR_ENTI_Msk (0x1UL << ETR_FFCR_ENTI_Pos) + +/* ATB Funnel Control Register bit fields */ +#define ATBFUNNEL_CTRLREG_ENS0_Pos (0UL) +#define ATBFUNNEL_CTRLREG_ENS0_Msk (0x1UL << ATBFUNNEL_CTRLREG_ENS0_Pos) +#define ATBFUNNEL_CTRLREG_ENS1_Pos (1UL) +#define ATBFUNNEL_CTRLREG_ENS1_Msk (0x1UL << ATBFUNNEL_CTRLREG_ENS1_Pos) +#define ATBFUNNEL_CTRLREG_ENS2_Pos (2UL) +#define ATBFUNNEL_CTRLREG_ENS2_Msk (0x1UL << ATBFUNNEL_CTRLREG_ENS2_Pos) +#define ATBFUNNEL_CTRLREG_ENS3_Pos (3UL) +#define ATBFUNNEL_CTRLREG_ENS3_Msk (0x1UL << ATBFUNNEL_CTRLREG_ENS3_Pos) +#define ATBFUNNEL_CTRLREG_ENS4_Pos (4UL) +#define ATBFUNNEL_CTRLREG_ENS4_Msk (0x1UL << ATBFUNNEL_CTRLREG_ENS4_Pos) +#define ATBFUNNEL_CTRLREG_ENS5_Pos (5UL) +#define ATBFUNNEL_CTRLREG_ENS5_Msk (0x1UL << ATBFUNNEL_CTRLREG_ENS5_Pos) +#define ATBFUNNEL_CTRLREG_ENS6_Pos (6UL) +#define ATBFUNNEL_CTRLREG_ENS6_Msk (0x1UL << ATBFUNNEL_CTRLREG_ENS6_Pos) +#define ATBFUNNEL_CTRLREG_ENS7_Pos (7UL) +#define ATBFUNNEL_CTRLREG_ENS7_Msk (0x1UL << ATBFUNNEL_CTRLREG_ENS7_Pos) +#define ATBFUNNEL_CTRLREG_HT_Pos (8UL) +#define ATBFUNNEL_CTRLREG_HT_Msk (0xFUL << ATBFUNNEL_CTRLREG_HT_Pos) + +/* TSGEN Counter Control Register bit fields */ +#define TSGEN_CNTCR_EN_Pos (0UL) +#define TSGEN_CNTCR_EN_Msk (0x1UL << TSGEN_CNTCR_EN_Pos) + +/** + * @brief Check if a CoreSight peripheral is locked + * + * @param base_addr Base address of CoreSight peripheral + * @return true if peripheral is locked, false otherwise + */ +static inline bool coresight_is_locked(mem_addr_t base_addr) +{ + uint32_t lsr = *(volatile uint32_t *)(base_addr + CORESIGHT_LSR_OFFSET); + + return (lsr & CORESIGHT_LSR_LOCKED_Msk) != 0; +} + +/** + * @brief Unlock a CoreSight peripheral + * + * @param base_addr Base address of CoreSight peripheral + * @retval 0 on success + * @retval -EIO if unlock operation failed + */ +static inline int coresight_unlock(mem_addr_t base_addr) +{ + *(volatile uint32_t *)(base_addr + CORESIGHT_LAR_OFFSET) = CORESIGHT_UNLOCK_KEY; + + if (coresight_is_locked(base_addr)) { + return -EIO; + } + + return 0; +} + +/** + * @brief Lock a CoreSight peripheral + * + * @param base_addr Base address of CoreSight peripheral + * @retval 0 on success + * @retval -EIO if lock operation failed + */ +static inline int coresight_lock(mem_addr_t base_addr) +{ + /* Write any value other than unlock key to Lock Access Register to lock */ + *(volatile uint32_t *)(base_addr + CORESIGHT_LAR_OFFSET) = 0x00000000; + + if (!coresight_is_locked(base_addr)) { + return -EIO; + } + + return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* CORESIGHT_ARM_H_ */ diff --git a/drivers/debug/debug_coresight_nrf.c b/drivers/debug/debug_coresight_nrf.c new file mode 100644 index 000000000000..7bc9bab68ee0 --- /dev/null +++ b/drivers/debug/debug_coresight_nrf.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#undef ETR_MODE_MODE_CIRCULARBUF + +#include "coresight_arm.h" + +#define DT_DRV_COMPAT nordic_coresight_nrf + +#include +LOG_MODULE_REGISTER(cs_trace, CONFIG_DEBUG_CORESIGHT_NRF_LOG_LEVEL); + +#define CTI_CH_TPIU_FLUSH_REQ_OFFSET (1) + +#define TS_CLOCKRATE \ + (DT_PROP(DT_NODELABEL(hsfll200), clock_frequency) / \ + CONFIG_DEBUG_CORESIGHT_NRF_TSGEN_CLK_DIV) + +#define ATBREPLICATOR_IDFILTER_FORWARD_STM \ + BIT(CONFIG_DEBUG_CORESIGHT_NRF_ATB_TRACE_ID_STM_GLOBAL >> 4) +#define ATBFUNNEL211_STM_ENS_MASK BIT(2) + +enum coresight_nrf_mode { + CORESIGHT_NRF_MODE_UNCONFIGURED, + CORESIGHT_NRF_MODE_STM_TPIU, + CORESIGHT_NRF_MODE_STM_ETR, +}; + +struct coresight_nrf_config { + enum coresight_nrf_mode mode; + const struct pinctrl_dev_config *pcfg; +}; + +static void nrf_tsgen_init(void) +{ + mem_addr_t tsgen = DT_REG_ADDR(DT_NODELABEL(tsgen)); + + coresight_unlock(tsgen); + + sys_write32(TS_CLOCKRATE, tsgen + TSGEN_CNTFID0_OFFSET); + sys_write32(TSGEN_CNTCR_EN_Msk, tsgen + TSGEN_CNTCR_OFFSET); + + coresight_lock(tsgen); + + LOG_INF("CoreSight Host TSGEN initialized with clockrate %u", TS_CLOCKRATE); +} + +static void nrf_cti_for_tpiu_init(void) +{ + mem_addr_t cti210 = DT_REG_ADDR(DT_NODELABEL(cti210)); + + coresight_unlock(cti210); + + /* Connect CTI channel to TPIU formatter flushin */ + sys_write32(BIT(CTI_CH_TPIU_FLUSH_REQ_OFFSET), cti210 + CTI_CTIOUTEN0_OFFSET); + sys_write32(BIT(CTI_CH_TPIU_FLUSH_REQ_OFFSET), cti210 + CTI_CTIGATE_OFFSET); + sys_write32(CTI_CTICONTROL_GLBEN_Msk, cti210 + CTI_CTICONTROL_OFFSET); + + coresight_lock(cti210); + + LOG_INF("CoreSight Host CTI initialized"); +} + +static void nrf_tpiu_init(void) +{ + mem_addr_t tpiu = DT_REG_ADDR(DT_NODELABEL(tpiu)); + + coresight_unlock(tpiu); + + sys_write32(BIT((CONFIG_DEBUG_CORESIGHT_NRF_TPIU_PORTSIZE - 1)), tpiu + TPIU_CSPSR_OFFSET); + + /* Continuous formatting */ + if (IS_ENABLED(CONFIG_DEBUG_CORESIGHT_NRF_TPIU_FFCR_TRIG)) { + sys_write32((TPIU_FFCR_ENFCONT_Msk | TPIU_FFCR_FONFLIN_Msk | TPIU_FFCR_ENFTC_Msk), + tpiu + TPIU_FFCR_OFFSET); + } else { + sys_write32((TPIU_FFCR_ENFCONT_Msk | TPIU_FFCR_ENFTC_Msk), tpiu + TPIU_FFCR_OFFSET); + } + + sys_write32(CONFIG_DEBUG_CORESIGHT_NRF_TPIU_SYNC_FRAME_COUNT, tpiu + TPIU_FSCR_OFFSET); + + coresight_lock(tpiu); + + LOG_INF("CoreSight Host TPIU initialized"); +} + +static void nrf_etr_init(uintptr_t buf, size_t buf_word_len) +{ + mem_addr_t etr = DT_REG_ADDR(DT_NODELABEL(etr)); + + coresight_unlock(etr); + + sys_write32(buf_word_len, etr + ETR_RSZ_OFFSET); + sys_write32(buf, etr + ETR_RWP_OFFSET); + sys_write32(buf, etr + ETR_DBALO_OFFSET); + sys_write32(0UL, etr + ETR_DBAHI_OFFSET); + sys_write32(ETR_FFCR_ENFT_Msk, etr + ETR_FFCR_OFFSET); + sys_write32(ETR_MODE_MODE_CIRCULARBUF, etr + ETR_MODE_OFFSET); + sys_write32(ETR_CTL_TRACECAPTEN_Msk, etr + ETR_CTL_OFFSET); + + coresight_lock(etr); + + LOG_INF("Coresight Host ETR initialized"); +} + +static void nrf_stm_init(void) +{ + mem_addr_t stm = DT_REG_ADDR(DT_NODELABEL(stm)); + + coresight_unlock(stm); + + sys_write32(1, stm + STM_STMAUXCR_OFFSET); + + sys_write32(TS_CLOCKRATE, stm + STM_STMTSFREQR_OFFSET); + + sys_write32((CONFIG_DEBUG_CORESIGHT_NRF_STM_SYNC_BYTE_COUNT & 0xFFF), + stm + STM_STMSYNCR_OFFSET); + + sys_write32(0xFFFFFFFF, stm + STM_STMSPER_OFFSET); + + if (IS_ENABLED(CONFIG_DEBUG_CORESIGHT_NRF_STM_HWEVENTS)) { + sys_write32(0xFFFFFFFF, stm + STM_STMHEER_OFFSET); + sys_write32((1 << STM_STMHEMCR_EN_Pos), stm + STM_STMHEMCR_OFFSET); + } + + sys_write32(((CONFIG_DEBUG_CORESIGHT_NRF_ATB_TRACE_ID_STM_GLOBAL & STM_STMTCSR_TRACEID_Msk) + << STM_STMTCSR_TRACEID_Pos) | + (1 << STM_STMTCSR_EN_Pos) | (1 << STM_STMTCSR_TSEN_Pos), + stm + STM_STMTCSR_OFFSET); + + coresight_lock(stm); + + LOG_INF("CoreSight STM initialized with clockrate %u", TS_CLOCKRATE); +} + +static void nrf_atbfunnel_init(mem_addr_t funnel_addr, uint32_t enable_set_mask) +{ + coresight_unlock(funnel_addr); + + uint32_t ctrlreg_old = sys_read32(funnel_addr + ATBFUNNEL_CTRLREG_OFFSET); + + const uint32_t funnel_hold_time = (((CONFIG_DEBUG_CORESIGHT_NRF_ATBFUNNEL_HOLD_TIME - 1) + << ATBFUNNEL_CTRLREG_HT_Pos) & + ATBFUNNEL_CTRLREG_HT_Msk); + + uint32_t ctrlreg_new = (ctrlreg_old & ~ATBFUNNEL_CTRLREG_HT_Msk) | funnel_hold_time | + (enable_set_mask & 0xFF); + + sys_write32(ctrlreg_new, funnel_addr + ATBFUNNEL_CTRLREG_OFFSET); + + coresight_lock(funnel_addr); +} + +static void nrf_atbreplicator_init(mem_addr_t replicator_addr, uint32_t filter, bool ch0_allow, + bool ch1_allow) +{ + coresight_unlock(replicator_addr); + + uint32_t ch0_current = sys_read32(replicator_addr + ATBREPLICATOR_IDFILTER0_OFFSET); + uint32_t ch1_current = sys_read32(replicator_addr + ATBREPLICATOR_IDFILTER1_OFFSET); + + if (ch0_allow) { + sys_write32(ch0_current & ~filter, + replicator_addr + ATBREPLICATOR_IDFILTER0_OFFSET); + } else { + sys_write32(ch0_current | filter, replicator_addr + ATBREPLICATOR_IDFILTER0_OFFSET); + } + + if (ch1_allow) { + sys_write32(ch1_current & ~filter, + replicator_addr + ATBREPLICATOR_IDFILTER1_OFFSET); + } else { + sys_write32(ch1_current | filter, replicator_addr + ATBREPLICATOR_IDFILTER1_OFFSET); + } + + coresight_lock(replicator_addr); +} + +static int coresight_nrf_init_stm_etr(uintptr_t buf, size_t buf_word_len) +{ + mem_addr_t atbfunnel211 = DT_REG_ADDR(DT_NODELABEL(atbfunnel211)); + mem_addr_t atbreplicator210 = DT_REG_ADDR(DT_NODELABEL(atbreplicator210)); + mem_addr_t atbreplicator213 = DT_REG_ADDR(DT_NODELABEL(atbreplicator213)); + + nrf_atbfunnel_init(atbfunnel211, ATBFUNNEL211_STM_ENS_MASK); + nrf_atbreplicator_init(atbreplicator210, ATBREPLICATOR_IDFILTER_FORWARD_STM, false, true); + nrf_atbreplicator_init(atbreplicator213, ATBREPLICATOR_IDFILTER_FORWARD_STM, false, true); + + nrf_tsgen_init(); + nrf_etr_init(buf, buf_word_len); + nrf_stm_init(); + + return 0; +} + +static int coresight_nrf_init_stm_tpiu(void) +{ + mem_addr_t atbfunnel211 = DT_REG_ADDR(DT_NODELABEL(atbfunnel211)); + mem_addr_t atbreplicator210 = DT_REG_ADDR(DT_NODELABEL(atbreplicator210)); + mem_addr_t atbreplicator213 = DT_REG_ADDR(DT_NODELABEL(atbreplicator213)); + + nrf_atbfunnel_init(atbfunnel211, ATBFUNNEL211_STM_ENS_MASK); + nrf_atbreplicator_init(atbreplicator210, ATBREPLICATOR_IDFILTER_FORWARD_STM, false, true); + nrf_atbreplicator_init(atbreplicator213, ATBREPLICATOR_IDFILTER_FORWARD_STM, true, false); + + nrf_tsgen_init(); + nrf_cti_for_tpiu_init(); + nrf_tpiu_init(); + nrf_stm_init(); + + return 0; +} + +static int coresight_nrf_init(const struct device *dev) +{ + int err; + struct coresight_nrf_config *cfg = (struct coresight_nrf_config *)dev->config; + + if (cfg->pcfg) { + err = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (err) { + LOG_ERR("Failed to configure pins (%d)", err); + return err; + } + } + + err = ironside_se_tdd_configure(IRONSIDE_SE_TDD_CONFIG_ON_DEFAULT); + if (err) { + LOG_ERR("Failed to configure TDD (%d)", err); + return err; + } + + switch (cfg->mode) { + case CORESIGHT_NRF_MODE_UNCONFIGURED: { + return 0; + } + case CORESIGHT_NRF_MODE_STM_TPIU: { + return coresight_nrf_init_stm_tpiu(); + } + case CORESIGHT_NRF_MODE_STM_ETR: { + uintptr_t etr_buffer = DT_REG_ADDR(DT_NODELABEL(etr_buffer)); + size_t buf_word_len = DT_REG_SIZE(DT_NODELABEL(etr_buffer)) / sizeof(uint32_t); + + return coresight_nrf_init_stm_etr(etr_buffer, buf_word_len); + } + default: { + LOG_ERR("Unsupported Coresight mode"); + return -ENOTSUP; + } + } + return 0; +} + +#define DEBUG_CORESIGHT_NRF_INIT_PRIORITY UTIL_INC(CONFIG_NRF_IRONSIDE_CALL_INIT_PRIORITY) + +#define CORESIGHT_NRF_INST(inst) \ + COND_CODE_1(DT_INST_PINCTRL_HAS_IDX(inst, 0), \ + (PINCTRL_DT_INST_DEFINE(inst);), ()) \ + \ + static struct coresight_nrf_config coresight_nrf_cfg_##inst = { \ + .mode = _CONCAT(CORESIGHT_NRF_MODE_, \ + DT_STRING_UPPER_TOKEN(DT_DRV_INST(inst), mode)), \ + .pcfg = COND_CODE_1(DT_INST_PINCTRL_HAS_IDX(inst, 0), \ + (PINCTRL_DT_INST_DEV_CONFIG_GET(inst)), \ + (NULL)) }; \ + \ + DEVICE_DT_INST_DEFINE(inst, coresight_nrf_init, NULL, NULL, &coresight_nrf_cfg_##inst, \ + POST_KERNEL, DEBUG_CORESIGHT_NRF_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(CORESIGHT_NRF_INST) diff --git a/drivers/misc/coresight/nrf_etr.c b/drivers/debug/debug_nrf_etr.c similarity index 90% rename from drivers/misc/coresight/nrf_etr.c rename to drivers/debug/debug_nrf_etr.c index bf1aecd6f5b4..d536cd4a9f40 100644 --- a/drivers/misc/coresight/nrf_etr.c +++ b/drivers/debug/debug_nrf_etr.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -29,15 +29,15 @@ LOG_MODULE_REGISTER(cs_etr_tbm); #define ETR_BUFFER_NODE DT_NODELABEL(etr_buffer) #define DROP_CHECK_PERIOD \ - COND_CODE_1(CONFIG_NRF_ETR_DECODE, \ - (CONFIG_NRF_ETR_DECODE_DROP_PERIOD), (0)) + COND_CODE_1(CONFIG_DEBUG_NRF_ETR_DECODE, \ + (CONFIG_DEBUG_NRF_ETR_DECODE_DROP_PERIOD), (0)) #define MIN_DATA (2 * CORESIGHT_TRACE_FRAME_SIZE32) /* Since ETR debug is a part of logging infrastructure, logging cannot be used * for debugging. Printk is used (assuming CONFIG_LOG_PRINTK=n) */ -#define DBG(...) IF_ENABLED(CONFIG_NRF_ETR_DEBUG, (printk(__VA_ARGS__))) +#define DBG(...) IF_ENABLED(CONFIG_DEBUG_NRF_ETR_DEBUG, (printk(__VA_ARGS__))) /** @brief Macro for dumping debug data. * @@ -86,10 +86,10 @@ static const struct device *uart_dev = DEVICE_DT_GET(UART_NODE); static uint32_t frame_buf0[CORESIGHT_TRACE_FRAME_SIZE32] DMM_MEMORY_SECTION(UART_NODE); static uint32_t frame_buf1[CORESIGHT_TRACE_FRAME_SIZE32] DMM_MEMORY_SECTION(UART_NODE); static uint32_t frame_buf_decode[CORESIGHT_TRACE_FRAME_SIZE32]; -static uint32_t *frame_buf = IS_ENABLED(CONFIG_NRF_ETR_DECODE) ? +static uint32_t *frame_buf = IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE) ? frame_buf_decode : frame_buf0; -K_KERNEL_STACK_DEFINE(etr_stack, CONFIG_NRF_ETR_STACK_SIZE); +K_KERNEL_STACK_DEFINE(etr_stack, CONFIG_DEBUG_NRF_ETR_STACK_SIZE); static struct k_thread etr_thread; BUILD_ASSERT((DT_REG_SIZE(ETR_BUFFER_NODE) % CONFIG_DCACHE_LINE_SIZE) == 0); @@ -134,9 +134,10 @@ static const char *const hw_evts[] = { "GD0 HS down", /* 31 Global domain high speed 0 down */ }; -#ifdef CONFIG_NRF_ETR_SHELL +#ifdef CONFIG_DEBUG_NRF_ETR_SHELL #define RX_BUF_SIZE \ - (CONFIG_NRF_ETR_SHELL_ASYNC_RX_BUFFER_SIZE * CONFIG_NRF_ETR_SHELL_ASYNC_RX_BUFFER_COUNT) + (CONFIG_DEBUG_NRF_ETR_SHELL_ASYNC_RX_BUFFER_SIZE * \ + CONFIG_DEBUG_NRF_ETR_SHELL_ASYNC_RX_BUFFER_COUNT) static void etr_timer_handler(struct k_timer *timer); K_TIMER_DEFINE(etr_timer, etr_timer_handler, NULL); @@ -278,7 +279,7 @@ static void message_process(union log_frontend_stmesp_demux_packet packet) */ static void sync_loss(void) { - if (IS_ENABLED(CONFIG_NRF_ETR_DECODE)) { + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE)) { mipi_stp_decoder_sync_loss(); log_frontend_stmesp_demux_reset(); oosync_cnt++; @@ -292,7 +293,7 @@ static void sync_loss(void) */ static void on_resync(void) { - if (IS_ENABLED(CONFIG_NRF_ETR_DECODE)) { + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE)) { in_sync = true; } } @@ -365,7 +366,7 @@ static void decoder_cb(enum mipi_stp_decoder_ctrl_type type, decoder_cb_debug(type, data, ts, marked); - if (!IS_ENABLED(CONFIG_NRF_ETR_DECODE)) { + if (!IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE)) { return; } @@ -549,7 +550,7 @@ static void dump_frame(uint8_t *buf) static void process(void) { static const uint32_t *const etr_buf = (uint32_t *)(DT_REG_ADDR(ETR_BUFFER_NODE)); - static uint32_t sync_cnt; + static uint32_t sync_cnt = CONFIG_DEBUG_NRF_ETR_SYNC_PERIOD; uint32_t pending; /* If function is called in panic mode then it may interrupt ongoing @@ -562,7 +563,7 @@ static void process(void) */ while ((pending = pending_data()) >= MIN_DATA) { /* Do not read the data that has already been read but not yet processed. */ - if (sync_cnt || (CONFIG_NRF_ETR_SYNC_PERIOD == 0)) { + if (sync_cnt || (CONFIG_DEBUG_NRF_ETR_SYNC_PERIOD == 0)) { sync_cnt--; sys_cache_data_invd_range((void *)&etr_buf[etr_rd_idx & wsize_mask], CORESIGHT_TRACE_FRAME_SIZE); @@ -572,11 +573,12 @@ static void process(void) rd_idx_inc(); __sync_synchronize(); } else { - sync_cnt = CONFIG_NRF_ETR_SYNC_PERIOD; + sync_cnt = CONFIG_DEBUG_NRF_ETR_SYNC_PERIOD; memset(frame_buf, 0xff, CORESIGHT_TRACE_FRAME_SIZE); } - if (IS_ENABLED(CONFIG_NRF_ETR_DECODE) || IS_ENABLED(CONFIG_NRF_ETR_DEBUG)) { + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE) || + IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DEBUG)) { if ((pending >= (wsize_mask - MIN_DATA)) || (pending_data() >= (wsize_mask - MIN_DATA))) { /* If before or after reading the frame it is close to full @@ -586,7 +588,7 @@ static void process(void) } process_frame((uint8_t *)frame_buf, pending); - if (IS_ENABLED(CONFIG_NRF_ETR_DECODE)) { + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE)) { process_messages(); } } else { @@ -612,7 +614,7 @@ static int decoder_init(void) } once = true; - if (IS_ENABLED(CONFIG_NRF_ETR_DECODE)) { + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE)) { static const struct log_frontend_stmesp_demux_config config = { .m_ids = stm_m_id, .m_ids_cnt = ARRAY_SIZE(stm_m_id), @@ -635,12 +637,12 @@ static int decoder_init(void) return 0; } -void nrf_etr_flush(void) +void debug_nrf_etr_flush(void) { int cnt = 4; - if (IS_ENABLED(CONFIG_NRF_ETR_DECODE) || - IS_ENABLED(CONFIG_NRF_ETR_DEBUG)) { + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE) || + IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DEBUG)) { (void)decoder_init(); } @@ -658,13 +660,13 @@ void nrf_etr_flush(void) irq_unlock(k); } -#ifndef CONFIG_NRF_ETR_SHELL +#ifndef CONFIG_DEBUG_NRF_ETR_SHELL static void etr_thread_func(void *dummy1, void *dummy2, void *dummy3) { uint64_t checkpoint = 0; - if (IS_ENABLED(CONFIG_NRF_ETR_DECODE) || - IS_ENABLED(CONFIG_NRF_ETR_DEBUG)) { + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE) || + IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DEBUG)) { int err; err = decoder_init(); @@ -688,7 +690,7 @@ static void etr_thread_func(void *dummy1, void *dummy2, void *dummy3) } } - k_sleep(K_MSEC(CONFIG_NRF_ETR_BACKOFF)); + k_sleep(K_MSEC(CONFIG_DEBUG_NRF_ETR_BACKOFF)); } } #endif @@ -703,7 +705,7 @@ static void uart_event_handler(const struct device *dev, struct uart_event *evt, case UART_TX_DONE: k_sem_give(&uart_sem); break; -#ifdef CONFIG_NRF_ETR_SHELL +#ifdef CONFIG_DEBUG_NRF_ETR_SHELL case UART_RX_RDY: uart_async_rx_on_rdy(&async_rx, evt->data.rx.buf, evt->data.rx.len); shell_handler(SHELL_TRANSPORT_EVT_RX_RDY, shell_context); @@ -729,7 +731,7 @@ static void uart_event_handler(const struct device *dev, struct uart_event *evt, break; case UART_RX_DISABLED: break; -#endif /* CONFIG_NRF_ETR_SHELL */ +#endif /* CONFIG_DEBUG_NRF_ETR_SHELL */ default: __ASSERT_NO_MSG(0); } @@ -743,7 +745,7 @@ static void tbm_event_handler(nrf_tbm_event_t event) tbm_full = true; } -#ifdef CONFIG_NRF_ETR_SHELL +#ifdef CONFIG_DEBUG_NRF_ETR_SHELL k_poll_signal_raise(&etr_shell.ctx->signals[SHELL_SIGNAL_LOG_MSG], 0); #else k_wakeup(&etr_thread); @@ -766,15 +768,16 @@ int etr_process_init(void) IRQ_CONNECT(DT_IRQN(DT_NODELABEL(tbm)), DT_IRQ(DT_NODELABEL(tbm), priority), nrfx_isr, nrfx_tbm_irq_handler, 0); irq_enable(DT_IRQN(DT_NODELABEL(tbm))); + nrfx_tbm_start(); -#ifdef CONFIG_NRF_ETR_SHELL +#ifdef CONFIG_DEBUG_NRF_ETR_SHELL uint32_t level = CONFIG_LOG_MAX_LEVEL; static const struct shell_backend_config_flags cfg_flags = SHELL_DEFAULT_BACKEND_CONFIG_FLAGS; shell_init(&etr_shell, NULL, cfg_flags, true, level); - k_timer_start(&etr_timer, K_MSEC(CONFIG_NRF_ETR_BACKOFF), K_NO_WAIT); - if (IS_ENABLED(CONFIG_NRF_ETR_DECODE) || IS_ENABLED(CONFIG_NRF_ETR_DEBUG)) { + k_timer_start(&etr_timer, K_MSEC(CONFIG_DEBUG_NRF_ETR_BACKOFF), K_NO_WAIT); + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DECODE) || IS_ENABLED(CONFIG_DEBUG_NRF_ETR_DEBUG)) { err = decoder_init(); if (err < 0) { return err; @@ -789,16 +792,26 @@ int etr_process_init(void) return 0; } -SYS_INIT(etr_process_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +#define NRF_ETR_INIT_PRIORITY UTIL_INC(UTIL_INC(CONFIG_NRF_IRONSIDE_CALL_INIT_PRIORITY)) -#ifdef CONFIG_NRF_ETR_SHELL +SYS_INIT(etr_process_init, POST_KERNEL, NRF_ETR_INIT_PRIORITY); + +#if defined(CONFIG_NORDIC_VPR_LAUNCHER) && defined(CONFIG_LOG_FRONTEND_STMESP_FSC) +/* TDD/ETR must be up and running before VPR cores are started as they write to + * ETR some vital initial data that cannot be lost. + */ +BUILD_ASSERT(CONFIG_NORDIC_VPR_LAUNCHER_INIT_PRIORITY > NRF_ETR_INIT_PRIORITY); +#endif + + +#ifdef CONFIG_DEBUG_NRF_ETR_SHELL static void etr_timer_handler(struct k_timer *timer) { if (pending_data() >= MIN_DATA) { k_poll_signal_raise(&etr_shell.ctx->signals[SHELL_SIGNAL_LOG_MSG], 0); } else { - k_timer_start(timer, K_MSEC(CONFIG_NRF_ETR_BACKOFF), K_NO_WAIT); + k_timer_start(timer, K_MSEC(CONFIG_DEBUG_NRF_ETR_BACKOFF), K_NO_WAIT); } } @@ -807,7 +820,7 @@ bool z_shell_log_backend_process(const struct shell_log_backend *backend) ARG_UNUSED(backend); process(); - k_timer_start(&etr_timer, K_MSEC(CONFIG_NRF_ETR_BACKOFF), K_NO_WAIT); + k_timer_start(&etr_timer, K_MSEC(CONFIG_DEBUG_NRF_ETR_BACKOFF), K_NO_WAIT); return false; } @@ -901,7 +914,7 @@ static int etr_shell_init(const struct shell_transport *transport, const void *c static const struct uart_async_rx_config async_rx_config = { .buffer = rx_buf, .length = sizeof(rx_buf), - .buf_cnt = CONFIG_NRF_ETR_SHELL_ASYNC_RX_BUFFER_COUNT, + .buf_cnt = CONFIG_DEBUG_NRF_ETR_SHELL_ASYNC_RX_BUFFER_COUNT, }; shell_context = context; @@ -939,6 +952,6 @@ static struct shell_transport transport = { }; static uint8_t shell_out_buffer[CONFIG_SHELL_PRINTF_BUFF_SIZE]; -Z_SHELL_DEFINE(etr_shell, CONFIG_NRF_ETR_SHELL_PROMPT, &transport, shell_out_buffer, NULL, +Z_SHELL_DEFINE(etr_shell, CONFIG_DEBUG_NRF_ETR_SHELL_PROMPT, &transport, shell_out_buffer, NULL, SHELL_FLAG_OLF_CRLF); -#endif /* CONFIG_NRF_ETR_SHELL */ +#endif /* CONFIG_DEBUG_NRF_ETR_SHELL */ diff --git a/drivers/disk/flashdisk.c b/drivers/disk/flashdisk.c index 1ac3d15ba62f..a2bb7d010365 100644 --- a/drivers/disk/flashdisk.c +++ b/drivers/disk/flashdisk.c @@ -424,7 +424,7 @@ static int disk_flash_access_write(struct disk_info *disk, const uint8_t *buff, end: k_mutex_unlock(&ctx->lock); - return 0; + return rc; } static int disk_flash_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) @@ -469,6 +469,8 @@ static const struct disk_operations flash_disk_ops = { .ioctl = disk_flash_access_ioctl, }; +#ifndef USE_PARTITION_MANAGER +/* The non-Partition manager, DTS based generators below */ #define DT_DRV_COMPAT zephyr_flash_disk #define PARTITION_PHANDLE(n) DT_PHANDLE_BY_IDX(DT_DRV_INST(n), partition, 0) @@ -510,6 +512,82 @@ DT_INST_FOREACH_STATUS_OKAY(VERIFY_CACHE_SIZE_IS_NOT_ZERO_IF_NOT_READ_ONLY) "Devicetree node " DT_NODE_PATH(DT_DRV_INST(n)) \ " has cache size which is not a multiple of its sector size"); DT_INST_FOREACH_STATUS_OKAY(VERIFY_CACHE_SIZE_IS_MULTIPLY_OF_SECTOR_SIZE) +#else /* ifndef USE_PARTITION_MANAGER */ +/* Partition Manager based generators below */ + +/* Gets the PM_..._EXTRA_PARAM_##param value */ +#define PM_FLASH_DISK_ENTRY_EXTRA_PARAM(name, param) PM_##name##_EXTRA_PARAM_disk_##param + +/* Gets the PM_..._NAME value which is originally cased, as in yaml, partition name */ +#define PM_FLASH_DISK_ENTRY_PARTITION_NAME(name) PM_##name##_NAME + +/* Generates flashdiskN_cache variable name, where N is partition ID */ +#define PM_FLASH_DISK_CACHE_VARIABLE(n) UTIL_CAT(flashdisk, UTIL_CAT(FIXED_PARTITION_ID(n), _cache)) + +/* Generate cache buffers */ +#define CACHE_SIZE(n) (COND_CODE_1(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, read_only), (0), (1)) * \ + PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, cache_size)) +#define DEFINE_FLASHDISKS_CACHE(n) \ + static uint8_t __aligned(4) PM_FLASH_DISK_CACHE_VARIABLE(n)[CACHE_SIZE(n)]; + +PM_FOREACH_AFFILIATED_TO_disk(DEFINE_FLASHDISKS_CACHE) + +/* Generated single Flash Disk device data from Partition Manager partition. + * Partition is required to have type set to disk in partition definitions: + * type: disk + * and following extra params can be provided: + * extra_params: { + * name = "", + * cache_size = , + * sector_size = , + * read_only = + * } + * where: + * is mandatory device name that will be used by Disk Access and FAT FS to mount device; + * is cache r/w cache size, which is mandatory if read_only = 0 or not present, + * and should be multiple of ; + * is mandatory device sector size information, usually should be erase page size, + * for flash devices, for example 4096 bytes; + * read_only is optional, if not present then assumed false; can be 0(false) or 1(true). + */ +#define DEFINE_FLASHDISKS_DEVICE(n) \ +{ \ + .info = { \ + .ops = &flash_disk_ops, \ + .name = STRINGIFY(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, name)), \ + }, \ + .area_id = FIXED_PARTITION_ID(n), \ + .offset = FIXED_PARTITION_OFFSET(n), \ + .cache = PM_FLASH_DISK_CACHE_VARIABLE(n), \ + .cache_size = sizeof(PM_FLASH_DISK_CACHE_VARIABLE(n)), \ + .size = FIXED_PARTITION_SIZE(n), \ + .sector_size = PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, sector_size), \ +}, + +/* The bellow used PM_FOREACH_TYPE_disk is generated by Partition Manager foreach + * loop macro. The lower case _disk is type name for which the macro has been generated; + * partition entry can have multiple types set and foreach macro will be generated + * for every type found across partition definitions. + */ +static struct flashdisk_data flash_disks[] = { + PM_FOREACH_AFFILIATED_TO_disk(DEFINE_FLASHDISKS_DEVICE) +}; + +#define VERIFY_CACHE_SIZE_IS_NOT_ZERO_IF_NOT_READ_ONLY(n) \ + COND_CODE_1(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, read_only), \ + (/* cache-size is not used for read-only disks */), \ + (BUILD_ASSERT(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, cache_size) != 0, \ + "Flash disk partition " STRINGIFY(PM_FLASH_DISK_ENTRY_PARTITION_NAME(n))\ + " must have non-zero cache-size");)) +PM_FOREACH_AFFILIATED_TO_disk(VERIFY_CACHE_SIZE_IS_NOT_ZERO_IF_NOT_READ_ONLY) + +#define VERIFY_CACHE_SIZE_IS_MULTIPLY_OF_SECTOR_SIZE(n) \ + BUILD_ASSERT(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, cache_size) % \ + PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, sector_size) == 0, \ + "Devicetree node " STRINGIFY(PM_FLASH_DISK_ENTRY_PARTITION_NAME(n)) \ + " has cache size which is not a multiple of its sector size"); +PM_FOREACH_AFFILIATED_TO_disk(VERIFY_CACHE_SIZE_IS_MULTIPLY_OF_SECTOR_SIZE) +#endif /* USE_PARTITION_MANAGER */ static int disk_flash_init(void) { diff --git a/drivers/entropy/Kconfig.psa_crypto b/drivers/entropy/Kconfig.psa_crypto index d06001225b05..18514a071d1c 100644 --- a/drivers/entropy/Kconfig.psa_crypto +++ b/drivers/entropy/Kconfig.psa_crypto @@ -7,6 +7,7 @@ config ENTROPY_PSA_CRYPTO_RNG bool "PSA Crypto Random source Entropy driver" depends on DT_HAS_ZEPHYR_PSA_CRYPTO_RNG_ENABLED select ENTROPY_HAS_DRIVER + select PSA_WANT_GENERATE_RANDOM default y help Enable the PSA Crypto source Entropy driver. diff --git a/drivers/flash/Kconfig.nrf_rram b/drivers/flash/Kconfig.nrf_rram index 3dea687a0f80..d8a5abf64b2e 100644 --- a/drivers/flash/Kconfig.nrf_rram +++ b/drivers/flash/Kconfig.nrf_rram @@ -56,8 +56,15 @@ config SOC_FLASH_NRF_RADIO_SYNC_NONE bool "none" help disable synchronization between flash memory driver and radio. + endchoice +config SOC_FLASH_NRF_THROTTLING + bool "Nordic nRFx throttling for flash write operations" + help + Enable throttling for flash write operations to avoid overloading the + flash memory controller. + config SOC_FLASH_NRF_TIMEOUT_MULTIPLIER int "Multiplier for flash operation timeouts [x0.1]" depends on !SOC_FLASH_NRF_RADIO_SYNC_NONE @@ -70,15 +77,31 @@ config SOC_FLASH_NRF_TIMEOUT_MULTIPLIER config NRF_RRAM_REGION_ADDRESS_RESOLUTION hex - default 0x400 + default 0x1000 help RRAMC's region protection address resolution. Applies to region with configurable start address. config NRF_RRAM_REGION_SIZE_UNIT hex - default 0x400 + default 0x1000 help Base unit for the size of RRAMC's region protection. +config NRF_RRAM_THROTTLING_DELAY + int "Delay between flash write operations" + depends on SOC_FLASH_NRF_THROTTLING + default 2000 + help + This is the delay (in microseconds) between consecutive flash write + operations when throttling is enabled. + +config NRF_RRAM_THROTTLING_DATA_BLOCK + int "Number of Data blocks for each flash write operations" + depends on SOC_FLASH_NRF_THROTTLING + default 16 + help + This is the number of data blocks (in number of 128-bit words) for flash write + operations when throttling is enabled. + endif # SOC_FLASH_NRF_RRAM diff --git a/drivers/flash/flash_mspi_nor.c b/drivers/flash/flash_mspi_nor.c index a634b3d9118b..405fd8800b36 100644 --- a/drivers/flash/flash_mspi_nor.c +++ b/drivers/flash/flash_mspi_nor.c @@ -26,8 +26,7 @@ LOG_MODULE_REGISTER(flash_mspi_nor, CONFIG_FLASH_LOG_LEVEL); #define NON_XIP_DEV_CFG_MASK (MSPI_DEVICE_CONFIG_ALL & ~XIP_DEV_CFG_MASK) static void set_up_xfer(const struct device *dev, enum mspi_xfer_direction dir); -static int perform_xfer(const struct device *dev, - uint8_t cmd, bool mem_access); +static int perform_xfer(const struct device *dev, uint8_t cmd); static int cmd_rdsr(const struct device *dev, uint8_t op_code, uint8_t *sr); static int wait_until_ready(const struct device *dev, k_timeout_t poll_period); static int cmd_wren(const struct device *dev); @@ -36,6 +35,26 @@ static int cmd_wrsr(const struct device *dev, uint8_t op_code, #include "flash_mspi_nor_quirks.h" +static bool in_octal_io(const struct device *dev) +{ + struct flash_mspi_nor_data *dev_data = dev->data; + + return dev_data->last_applied_cfg && + dev_data->last_applied_cfg->io_mode == MSPI_IO_MODE_OCTAL; +} + +static bool is_quad_enable_needed(const struct mspi_dev_cfg *cfg) +{ + return cfg && (cfg->io_mode == MSPI_IO_MODE_QUAD_1_1_4 || + cfg->io_mode == MSPI_IO_MODE_QUAD_1_4_4); +} + +static bool is_octal_enable_needed(const struct mspi_dev_cfg *cfg) +{ + return cfg && (cfg->io_mode == MSPI_IO_MODE_OCTAL_1_1_8 || + cfg->io_mode == MSPI_IO_MODE_OCTAL_1_8_8); +} + static void set_up_xfer(const struct device *dev, enum mspi_xfer_direction dir) { const struct flash_mspi_nor_config *dev_config = dev->config; @@ -77,8 +96,7 @@ static uint16_t get_extended_command(const struct device *dev, return ((uint16_t)cmd << 8) | cmd_extension; } -static int perform_xfer(const struct device *dev, - uint8_t cmd, bool mem_access) +static int perform_xfer(const struct device *dev, uint8_t cmd) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; @@ -86,7 +104,7 @@ static int perform_xfer(const struct device *dev, int rc; if (dev_data->cmd_info.cmd_extension != CMD_EXTENSION_NONE && - dev_data->in_target_io_mode) { + in_octal_io(dev)) { dev_data->xfer.cmd_length = 2; dev_data->packet.cmd = get_extended_command(dev, cmd); } else { @@ -94,45 +112,31 @@ static int perform_xfer(const struct device *dev, dev_data->packet.cmd = cmd; } - if (dev_config->multi_io_cmd || - dev_config->mspi_nor_cfg.io_mode == MSPI_IO_MODE_SINGLE) { - /* If multiple IO lines are used in all the transfer phases - * or in none of them, there's no need to switch the IO mode. - */ - } else if (mem_access) { - /* For commands accessing the flash memory (read and program), - * ensure that the target IO mode is active. - */ - if (!dev_data->in_target_io_mode) { - cfg = &dev_config->mspi_nor_cfg; - } - } else { - /* For all other commands, switch to Single IO mode if a given - * command needs the data or address phase and in the target IO - * mode multiple IO lines are used in these phases. - */ - if (dev_data->in_target_io_mode) { - if (dev_data->packet.num_bytes != 0 || - (dev_data->xfer.addr_length != 0 && - !dev_config->single_io_addr)) { - /* Only the IO mode is to be changed, so the - * initial configuration structure can be used - * for this operation. - */ - cfg = &dev_config->mspi_nor_init_cfg; - } + /* Commands before chip is initialized manually apply a MSPI config + * which all flash chips support by JEDEC standard. Do not switch + * to device tree config yet. + * If multiple IO lines are used in all the transfer phases + * there's no need to switch the IO mode. + */ + if (dev_data->chip_initialized && !dev_config->multi_io_cmd) { + if (cmd == dev_data->cmd_info.read_cmd) { + cfg = dev_data->read_cfg; + } else if (cmd == dev_data->cmd_info.pp_cmd) { + cfg = dev_data->write_cfg; + } else { + /* For all other commands, use control command config */ + cfg = &dev_config->mspi_control_cfg; } } - if (cfg) { + if (cfg && cfg != dev_data->last_applied_cfg) { rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, - MSPI_DEVICE_CONFIG_IO_MODE, cfg); + MSPI_DEVICE_CONFIG_IO_MODE | MSPI_DEVICE_CONFIG_FREQUENCY, cfg); if (rc < 0) { LOG_ERR("%s: dev_config() failed: %d", __func__, rc); return rc; } - - dev_data->in_target_io_mode = mem_access; + dev_data->last_applied_cfg = cfg; } rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, @@ -151,14 +155,14 @@ static int cmd_rdsr(const struct device *dev, uint8_t op_code, uint8_t *sr) int rc; set_up_xfer(dev, MSPI_RX); - if (dev_data->in_target_io_mode) { + if (in_octal_io(dev)) { dev_data->xfer.rx_dummy = dev_data->cmd_info.rdsr_dummy; dev_data->xfer.addr_length = dev_data->cmd_info.rdsr_addr_4 ? 4 : 0; } dev_data->packet.num_bytes = sizeof(uint8_t); dev_data->packet.data_buf = sr; - rc = perform_xfer(dev, op_code, false); + rc = perform_xfer(dev, op_code); if (rc < 0) { LOG_ERR("%s 0x%02x failed: %d", __func__, op_code, rc); return rc; @@ -194,7 +198,7 @@ static int cmd_wren(const struct device *dev) int rc; set_up_xfer(dev, MSPI_TX); - rc = perform_xfer(dev, SPI_NOR_CMD_WREN, false); + rc = perform_xfer(dev, SPI_NOR_CMD_WREN); if (rc < 0) { LOG_ERR("%s failed: %d", __func__, rc); return rc; @@ -217,7 +221,7 @@ static int cmd_wrsr(const struct device *dev, uint8_t op_code, set_up_xfer(dev, MSPI_TX); dev_data->packet.num_bytes = sr_cnt; dev_data->packet.data_buf = sr; - rc = perform_xfer(dev, op_code, false); + rc = perform_xfer(dev, op_code); if (rc < 0) { LOG_ERR("%s 0x%02x failed: %d", __func__, op_code, rc); return rc; @@ -237,7 +241,9 @@ static int acquire(const struct device *dev) struct flash_mspi_nor_data *dev_data = dev->data; int rc; +#if defined(CONFIG_MULTITHREADING) k_sem_take(&dev_data->acquired, K_FOREVER); +#endif rc = pm_device_runtime_get(dev_config->bus); if (rc < 0) { @@ -260,7 +266,7 @@ static int acquire(const struct device *dev) LOG_ERR("mspi_dev_config() failed: %d", rc); } else { if (dev_config->multiperipheral_bus) { - dev_data->in_target_io_mode = true; + dev_data->last_applied_cfg = &dev_config->mspi_nor_cfg; } return 0; @@ -269,21 +275,27 @@ static int acquire(const struct device *dev) (void)pm_device_runtime_put(dev_config->bus); } +#if defined(CONFIG_MULTITHREADING) k_sem_give(&dev_data->acquired); +#endif + return rc; } static void release(const struct device *dev) { const struct flash_mspi_nor_config *dev_config = dev->config; - struct flash_mspi_nor_data *dev_data = dev->data; /* This releases the MSPI controller. */ (void)mspi_get_channel_status(dev_config->bus, 0); (void)pm_device_runtime_put(dev_config->bus); +#if defined(CONFIG_MULTITHREADING) + struct flash_mspi_nor_data *dev_data = dev->data; + k_sem_give(&dev_data->acquired); +#endif } static inline uint32_t dev_flash_size(const struct device *dev) @@ -328,6 +340,7 @@ static uint8_t get_rx_dummy(const struct device *dev) static int api_read(const struct device *dev, off_t addr, void *dest, size_t size) { + const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; const uint32_t flash_size = dev_flash_size(dev); int rc; @@ -345,11 +358,26 @@ static int api_read(const struct device *dev, off_t addr, void *dest, return rc; } - set_up_xfer_with_addr(dev, MSPI_RX, addr); - dev_data->xfer.rx_dummy = get_rx_dummy(dev); - dev_data->packet.data_buf = dest; - dev_data->packet.num_bytes = size; - rc = perform_xfer(dev, dev_data->cmd_info.read_cmd, true); + while (size > 0) { + uint32_t to_read; + + if (dev_config->packet_data_limit && + dev_config->packet_data_limit < size) { + to_read = dev_config->packet_data_limit; + } else { + to_read = size; + } + + set_up_xfer_with_addr(dev, MSPI_RX, addr); + dev_data->xfer.rx_dummy = get_rx_dummy(dev); + dev_data->packet.data_buf = dest; + dev_data->packet.num_bytes = to_read; + rc = perform_xfer(dev, dev_data->cmd_info.read_cmd); + + addr += to_read; + dest = (uint8_t *)dest + to_read; + size -= to_read; + } release(dev); @@ -395,7 +423,7 @@ static int api_write(const struct device *dev, off_t addr, const void *src, set_up_xfer_with_addr(dev, MSPI_TX, addr); dev_data->packet.data_buf = (uint8_t *)src; dev_data->packet.num_bytes = to_write; - rc = perform_xfer(dev, dev_data->cmd_info.pp_cmd, true); + rc = perform_xfer(dev, dev_data->cmd_info.pp_cmd); if (rc < 0) { LOG_ERR("Page program xfer failed: %d", rc); break; @@ -467,7 +495,7 @@ static int api_erase(const struct device *dev, off_t addr, size_t size) if (size == flash_size) { /* Chip erase. */ set_up_xfer(dev, MSPI_TX); - rc = perform_xfer(dev, SPI_NOR_CMD_CE, false); + rc = perform_xfer(dev, SPI_NOR_CMD_CE); size -= flash_size; } else { @@ -476,7 +504,7 @@ static int api_erase(const struct device *dev, off_t addr, size_t size) if (best_et != NULL) { set_up_xfer_with_addr(dev, MSPI_TX, addr); - rc = perform_xfer(dev, best_et->cmd, false); + rc = perform_xfer(dev, best_et->cmd); addr += BIT(best_et->exp); size -= BIT(best_et->exp); @@ -530,7 +558,7 @@ static int sfdp_read(const struct device *dev, off_t addr, void *dest, int rc; set_up_xfer(dev, MSPI_RX); - if (dev_data->in_target_io_mode) { + if (in_octal_io(dev)) { dev_data->xfer.rx_dummy = dev_data->cmd_info.sfdp_dummy_20 ? 20 : 8; dev_data->xfer.addr_length = dev_data->cmd_info.sfdp_addr_4 @@ -542,7 +570,7 @@ static int sfdp_read(const struct device *dev, off_t addr, void *dest, dev_data->packet.address = addr; dev_data->packet.data_buf = dest; dev_data->packet.num_bytes = size; - rc = perform_xfer(dev, JESD216_CMD_READ_SFDP, false); + rc = perform_xfer(dev, JESD216_CMD_READ_SFDP); if (rc < 0) { LOG_ERR("Read SFDP xfer failed: %d", rc); } @@ -556,14 +584,14 @@ static int read_jedec_id(const struct device *dev, uint8_t *id) int rc; set_up_xfer(dev, MSPI_RX); - if (dev_data->in_target_io_mode) { + if (in_octal_io(dev)) { dev_data->xfer.rx_dummy = dev_data->cmd_info.rdid_dummy; dev_data->xfer.addr_length = dev_data->cmd_info.rdid_addr_4 ? 4 : 0; } dev_data->packet.data_buf = id; dev_data->packet.num_bytes = JESD216_READ_ID_LEN; - rc = perform_xfer(dev, SPI_NOR_CMD_RDID, false); + rc = perform_xfer(dev, SPI_NOR_CMD_RDID); if (rc < 0) { LOG_ERR("Read JEDEC ID failed: %d", rc); } @@ -753,7 +781,7 @@ static int octal_enable_set(const struct device *dev, bool enable) dev_data->packet.address = 0x02; dev_data->packet.num_bytes = sizeof(uint8_t); dev_data->packet.data_buf = &status_reg; - rc = perform_xfer(dev, op_code, false); + rc = perform_xfer(dev, op_code); if (rc < 0) { LOG_ERR("cmd_rdsr 0x%02x failed: %d", op_code, rc); return rc; @@ -789,7 +817,7 @@ static int enter_4byte_addressing_mode(const struct device *dev) } set_up_xfer(dev, MSPI_TX); - rc = perform_xfer(dev, 0xB7, false); + rc = perform_xfer(dev, 0xB7); if (rc < 0) { LOG_ERR("Command 0xB7 failed: %d", rc); return rc; @@ -802,12 +830,11 @@ static int switch_to_target_io_mode(const struct device *dev) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; - enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode; int rc = 0; if (dev_data->switch_info.quad_enable_req != JESD216_DW15_QER_VAL_NONE) { - bool quad_needed = io_mode == MSPI_IO_MODE_QUAD_1_1_4 || - io_mode == MSPI_IO_MODE_QUAD_1_4_4; + bool quad_needed = is_quad_enable_needed(dev_data->read_cfg) || + is_quad_enable_needed(dev_data->write_cfg); rc = quad_enable_set(dev, quad_needed); if (rc < 0) { @@ -817,8 +844,8 @@ static int switch_to_target_io_mode(const struct device *dev) } if (dev_data->switch_info.octal_enable_req != OCTAL_ENABLE_REQ_NONE) { - bool octal_needed = io_mode == MSPI_IO_MODE_OCTAL_1_1_8 || - io_mode == MSPI_IO_MODE_OCTAL_1_8_8; + bool octal_needed = is_octal_enable_needed(dev_data->read_cfg) || + is_octal_enable_needed(dev_data->write_cfg); rc = octal_enable_set(dev, octal_needed); if (rc < 0) { @@ -843,9 +870,14 @@ static int switch_to_target_io_mode(const struct device *dev) } } - return mspi_dev_config(dev_config->bus, &dev_config->mspi_id, + rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, NON_XIP_DEV_CFG_MASK, &dev_config->mspi_nor_cfg); + if (rc < 0) { + return rc; + } + dev_data->last_applied_cfg = &dev_config->mspi_nor_cfg; + return 0; } #if defined(WITH_SUPPLY_GPIO) @@ -908,14 +940,14 @@ static int soft_reset_66_99(const struct device *dev) int rc; set_up_xfer(dev, MSPI_TX); - rc = perform_xfer(dev, SPI_NOR_CMD_RESET_EN, false); + rc = perform_xfer(dev, SPI_NOR_CMD_RESET_EN); if (rc < 0) { LOG_ERR("CMD_RESET_EN failed: %d", rc); return rc; } set_up_xfer(dev, MSPI_TX); - rc = perform_xfer(dev, SPI_NOR_CMD_RESET_MEM, false); + rc = perform_xfer(dev, SPI_NOR_CMD_RESET_MEM); if (rc < 0) { LOG_ERR("CMD_RESET_MEM failed: %d", rc); return rc; @@ -941,8 +973,7 @@ static int soft_reset(const struct device *dev) LOG_ERR("%s: dev_config() failed: %d", __func__, rc); return rc; } - - dev_data->in_target_io_mode = true; + dev_data->last_applied_cfg = &dev_config->mspi_nor_cfg; rc = soft_reset_66_99(dev); if (rc < 0) { @@ -951,13 +982,12 @@ static int soft_reset(const struct device *dev) rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, MSPI_DEVICE_CONFIG_IO_MODE, - &dev_config->mspi_nor_init_cfg); + &dev_config->mspi_control_cfg); if (rc < 0) { LOG_ERR("%s: dev_config() failed: %d", __func__, rc); return rc; } - - dev_data->in_target_io_mode = false; + dev_data->last_applied_cfg = &dev_config->mspi_control_cfg; } rc = soft_reset_66_99(dev); @@ -973,22 +1003,24 @@ static int flash_chip_init(const struct device *dev) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; + struct mspi_dev_cfg mspi_nor_init_cfg; uint8_t id[JESD216_READ_ID_LEN] = {0}; uint16_t dts_cmd = 0; uint32_t sfdp_signature; bool flash_reset = false; int rc; + /* Do initial checks at max 50MHz required to be supported by JEDEC */ + memcpy(&mspi_nor_init_cfg, &dev_config->mspi_control_cfg, sizeof(mspi_nor_init_cfg)); + mspi_nor_init_cfg.freq = MIN(dev_config->mspi_control_cfg.freq, MHZ(50)); rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, MSPI_DEVICE_CONFIG_ALL, - &dev_config->mspi_nor_init_cfg); + &mspi_nor_init_cfg); if (rc < 0) { LOG_ERR("%s: dev_config() failed: %d", __func__, rc); return rc; } - dev_data->in_target_io_mode = false; - #if defined(WITH_SUPPLY_GPIO) if (dev_config->supply.port) { rc = power_supply(dev); @@ -1062,6 +1094,33 @@ static int flash_chip_init(const struct device *dev) } } + /* If read/write commands and frequency do not match the default + * MSPI device configuration, store new ones for those commands + * specifically. + */ + if (dev_config->read_io_mode == dev_config->mspi_nor_cfg.io_mode && + dev_config->read_freq == dev_config->mspi_nor_cfg.freq) { + dev_data->read_cfg = &dev_config->mspi_nor_cfg; + } else { + memcpy(&dev_data->mspi_dev_read_cfg, &dev_config->mspi_nor_cfg, + sizeof(dev_config->mspi_nor_cfg)); + dev_data->mspi_dev_read_cfg.io_mode = dev_config->read_io_mode; + dev_data->mspi_dev_read_cfg.freq = dev_config->read_freq; + dev_data->read_cfg = &dev_data->mspi_dev_read_cfg; + } + + if (dev_config->write_io_mode == dev_config->mspi_nor_cfg.io_mode && + dev_config->write_freq == dev_config->mspi_nor_cfg.freq) { + dev_data->write_cfg = &dev_config->mspi_nor_cfg; + } else { + memcpy(&dev_data->mspi_dev_write_cfg, &dev_config->mspi_nor_cfg, + sizeof(dev_config->mspi_nor_cfg)); + dev_data->mspi_dev_write_cfg.io_mode = dev_config->write_io_mode; + dev_data->mspi_dev_write_cfg.freq = dev_config->write_freq; + dev_data->write_cfg = &dev_data->mspi_dev_write_cfg; + } + + if (dev_config->jedec_id_specified) { rc = read_jedec_id(dev, id); if (rc < 0) { @@ -1085,8 +1144,7 @@ static int flash_chip_init(const struct device *dev) LOG_ERR("Failed to switch to target io mode: %d", rc); return rc; } - - dev_data->in_target_io_mode = true; + dev_data->chip_initialized = true; if (IS_ENABLED(CONFIG_FLASH_MSPI_NOR_USE_SFDP)) { /* Read the SFDP signature to test if communication with @@ -1215,7 +1273,9 @@ static int drv_init(const struct device *dev) } } +#if defined(CONFIG_MULTITHREADING) k_sem_init(&dev_data->acquired, 1, K_SEM_MAX_LIMIT); +#endif return pm_device_driver_init(dev, dev_pm_action_cb); } @@ -1235,10 +1295,12 @@ static DEVICE_API(flash, drv_api) = { #endif }; -#define FLASH_INITIAL_CONFIG(inst) \ +#define FLASH_MSPI_MAX_FREQ(inst) DT_INST_PROP(inst, mspi_max_frequency) + +#define FLASH_CONTROL_CMD_CONFIG(inst) \ { \ .ce_num = DT_INST_PROP_OR(inst, mspi_hardware_ce_num, 0), \ - .freq = MIN(DT_INST_PROP(inst, mspi_max_frequency), MHZ(50)), \ + .freq = FLASH_MSPI_MAX_FREQ(inst), \ .io_mode = MSPI_IO_MODE_SINGLE, \ .data_rate = MSPI_DATA_RATE_SINGLE, \ .cpp = MSPI_CPP_MODE_0, \ @@ -1284,18 +1346,27 @@ BUILD_ASSERT((FLASH_SIZE(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) == 0, \ #define INIT_PRIORITY UTIL_INC(CONFIG_MSPI_INIT_PRIORITY) #endif +#define PACKET_DATA_LIMIT(inst) \ + DT_PROP_OR(DT_INST_BUS(inst), packet_data_limit, 0) + #define FLASH_MSPI_NOR_INST(inst) \ + BUILD_ASSERT(!PACKET_DATA_LIMIT(inst) || \ + FLASH_PAGE_SIZE(inst) <= PACKET_DATA_LIMIT(inst), \ + "Page size for " DT_NODE_FULL_NAME(DT_DRV_INST(inst)) \ + " exceeds controller packet data limit"); \ SFDP_BUILD_ASSERTS(inst); \ PM_DEVICE_DT_INST_DEFINE(inst, dev_pm_action_cb); \ DEFAULT_ERASE_TYPES_DEFINE(inst); \ static struct flash_mspi_nor_data dev##inst##_data; \ static const struct flash_mspi_nor_config dev##inst##_config = { \ .bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .packet_data_limit = DT_PROP_OR(DT_INST_BUS(inst), \ + packet_data_limit, 0), \ .flash_size = FLASH_SIZE(inst), \ .page_size = FLASH_PAGE_SIZE(inst), \ .mspi_id = MSPI_DEVICE_ID_DT_INST(inst), \ .mspi_nor_cfg = MSPI_DEVICE_CONFIG_DT_INST(inst), \ - .mspi_nor_init_cfg = FLASH_INITIAL_CONFIG(inst), \ + .mspi_control_cfg = FLASH_CONTROL_CMD_CONFIG(inst), \ IF_ENABLED(CONFIG_MSPI_XIP, \ (.xip_cfg = MSPI_XIP_CONFIG_DT_INST(inst),)) \ IF_ENABLED(WITH_SUPPLY_GPIO, \ @@ -1313,6 +1384,14 @@ BUILD_ASSERT((FLASH_SIZE(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) == 0, \ .default_erase_types = DEFAULT_ERASE_TYPES(inst), \ .default_cmd_info = DEFAULT_CMD_INFO(inst), \ .default_switch_info = DEFAULT_SWITCH_INFO(inst), \ + .read_freq = DT_INST_PROP_OR(inst, read_frequency, \ + FLASH_MSPI_MAX_FREQ(inst)), \ + .read_io_mode = DT_INST_ENUM_IDX_OR(inst, read_io_mode, \ + DT_INST_ENUM_IDX(inst, mspi_io_mode)), \ + .write_freq = DT_INST_PROP_OR(inst, write_frequency, \ + FLASH_MSPI_MAX_FREQ(inst)), \ + .write_io_mode = DT_INST_ENUM_IDX_OR(inst, write_io_mode, \ + DT_INST_ENUM_IDX(inst, mspi_io_mode)), \ .jedec_id_specified = DT_INST_NODE_HAS_PROP(inst, jedec_id), \ .rx_dummy_specified = DT_INST_NODE_HAS_PROP(inst, rx_dummy), \ .multiperipheral_bus = DT_PROP(DT_INST_BUS(inst), \ diff --git a/drivers/flash/flash_mspi_nor.h b/drivers/flash/flash_mspi_nor.h index 480bccce4729..6252b838c0cd 100644 --- a/drivers/flash/flash_mspi_nor.h +++ b/drivers/flash/flash_mspi_nor.h @@ -70,11 +70,12 @@ struct flash_mspi_nor_switch_info { struct flash_mspi_nor_config { const struct device *bus; + uint32_t packet_data_limit; uint32_t flash_size; uint16_t page_size; struct mspi_dev_id mspi_id; struct mspi_dev_cfg mspi_nor_cfg; - struct mspi_dev_cfg mspi_nor_init_cfg; + struct mspi_dev_cfg mspi_control_cfg; #if defined(CONFIG_MSPI_XIP) struct mspi_xip_cfg xip_cfg; #endif @@ -95,6 +96,10 @@ struct flash_mspi_nor_config { const struct jesd216_erase_type *default_erase_types; struct flash_mspi_nor_cmd_info default_cmd_info; struct flash_mspi_nor_switch_info default_switch_info; + uint32_t read_freq; + enum mspi_io_mode read_io_mode; + uint32_t write_freq; + enum mspi_io_mode write_io_mode; bool jedec_id_specified : 1; bool rx_dummy_specified : 1; bool multiperipheral_bus : 1; @@ -104,13 +109,20 @@ struct flash_mspi_nor_config { }; struct flash_mspi_nor_data { +#if defined(CONFIG_MULTITHREADING) struct k_sem acquired; +#endif struct mspi_xfer_packet packet; struct mspi_xfer xfer; struct jesd216_erase_type erase_types[JESD216_NUM_ERASE_TYPES]; struct flash_mspi_nor_cmd_info cmd_info; struct flash_mspi_nor_switch_info switch_info; - bool in_target_io_mode; + const struct mspi_dev_cfg *last_applied_cfg; + bool chip_initialized; + const struct mspi_dev_cfg *read_cfg; + struct mspi_dev_cfg mspi_dev_read_cfg; + const struct mspi_dev_cfg *write_cfg; + struct mspi_dev_cfg mspi_dev_write_cfg; }; #ifdef __cplusplus diff --git a/drivers/flash/flash_mspi_nor_quirks.h b/drivers/flash/flash_mspi_nor_quirks.h index d58fbea4ff9b..83480b4643a8 100644 --- a/drivers/flash/flash_mspi_nor_quirks.h +++ b/drivers/flash/flash_mspi_nor_quirks.h @@ -80,7 +80,7 @@ static inline int mxicy_mx25r_post_switch_mode(const struct device *dev) set_up_xfer(dev, MSPI_TX); dev_data->packet.data_buf = mxicy_mx25r_hp_payload; dev_data->packet.num_bytes = sizeof(mxicy_mx25r_hp_payload); - rc = perform_xfer(dev, SPI_NOR_CMD_WRSR, false); + rc = perform_xfer(dev, SPI_NOR_CMD_WRSR); if (rc < 0) { return rc; } @@ -101,7 +101,7 @@ static inline int mxicy_mx25r_post_switch_mode(const struct device *dev) set_up_xfer(dev, MSPI_RX); dev_data->packet.num_bytes = sizeof(config); dev_data->packet.data_buf = config; - rc = perform_xfer(dev, SPI_NOR_CMD_RDCR, false); + rc = perform_xfer(dev, SPI_NOR_CMD_RDCR); if (rc < 0) { return rc; } @@ -159,7 +159,7 @@ static inline int mxicy_mx25u_post_switch_mode(const struct device *dev) dev_data->packet.address = 0; dev_data->packet.data_buf = &opi_enable; dev_data->packet.num_bytes = sizeof(opi_enable); - return perform_xfer(dev, SPI_NOR_CMD_WR_CFGREG2, false); + return perform_xfer(dev, SPI_NOR_CMD_WR_CFGREG2); } static int mxicy_mx25u_pre_init(const struct device *dev) @@ -192,7 +192,7 @@ static int mxicy_mx25u_pre_init(const struct device *dev) dev_data->packet.address = 0x300; dev_data->packet.data_buf = &cfg_reg; dev_data->packet.num_bytes = sizeof(cfg_reg); - rc = perform_xfer(dev, SPI_NOR_CMD_RD_CFGREG2, false); + rc = perform_xfer(dev, SPI_NOR_CMD_RD_CFGREG2); if (rc < 0) { LOG_ERR("Failed to read Dummy Cycle from CFGREG2"); return rc; diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index e9eb5a17302b..110a2d27c7e9 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -481,7 +481,6 @@ static int qspi_send_cmd(const struct device *dev, const struct qspi_cmd *cmd, return qspi_get_zephyr_ret_code(res); } -#if !IS_EQUAL(INST_0_QER, JESD216_DW15_QER_VAL_NONE) /* RDSR. Negative value is error. */ static int qspi_rdsr(const struct device *dev, uint8_t sr_num) { @@ -525,6 +524,7 @@ static int qspi_wait_while_writing(const struct device *dev, k_timeout_t poll_pe return (rc < 0) ? rc : 0; } +#if !IS_EQUAL(INST_0_QER, JESD216_DW15_QER_VAL_NONE) static int qspi_wrsr(const struct device *dev, uint8_t sr_val, uint8_t sr_num) { int rc = 0; @@ -657,7 +657,6 @@ static int qspi_erase(const struct device *dev, uint32_t addr, uint32_t size) static int configure_chip(const struct device *dev) { - const struct qspi_nor_config *dev_config = dev->config; int rc = 0; /* Set QE to match transfer mode. If not using quad @@ -668,6 +667,7 @@ static int configure_chip(const struct device *dev) * S2B1v1/4/5/6. Other options require more logic. */ #if !IS_EQUAL(INST_0_QER, JESD216_DW15_QER_VAL_NONE) + const struct qspi_nor_config *dev_config = dev->config; nrf_qspi_prot_conf_t const *prot_if = &dev_config->nrfx_cfg.prot_if; bool qe_value = (prot_if->writeoc == NRF_QSPI_WRITEOC_PP4IO) || diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index 9e1ba68319ff..574739082dc4 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -37,6 +37,11 @@ LOG_MODULE_REGISTER(flash_nrf); #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER +#include +#include +#endif /* CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER */ + #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE #define FLASH_SLOT_WRITE 7500 #if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE) @@ -166,6 +171,12 @@ static int flash_nrf_read(const struct device *dev, off_t addr, } #endif +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER && PM_APP_ADDRESS + if (addr < PM_APP_ADDRESS) { + return soc_secure_mem_read(data, (void *)addr, len); + } +#endif + nrf_nvmc_buffer_read(data, (uint32_t)addr, len); return 0; diff --git a/drivers/flash/soc_flash_nrf_rram.c b/drivers/flash/soc_flash_nrf_rram.c index d26a15cf7236..84c7e958f3cd 100644 --- a/drivers/flash/soc_flash_nrf_rram.c +++ b/drivers/flash/soc_flash_nrf_rram.c @@ -54,6 +54,11 @@ LOG_MODULE_REGISTER(flash_nrf_rram, CONFIG_FLASH_LOG_LEVEL); #define WRITE_BLOCK_SIZE_FROM_DT DT_PROP(RRAM, write_block_size) #define ERASE_VALUE 0xFF +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER +#include +#include +#endif /* CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER */ + #ifdef CONFIG_MULTITHREADING static struct k_sem sem_lock; #define SYNC_INIT() k_sem_init(&sem_lock, 1, 1) @@ -159,11 +164,24 @@ static void rram_write(off_t addr, const void *data, size_t len) nrf_rramc_config_set(NRF_RRAMC, &config); #endif - if (data) { - memcpy((void *)addr, data, len); - } else { - memset((void *)addr, ERASE_VALUE, len); + size_t chunk_len = len; + +#ifdef CONFIG_SOC_FLASH_NRF_THROTTLING + while (len > 0) { + chunk_len = MIN(len, CONFIG_NRF_RRAM_THROTTLING_DATA_BLOCK * WRITE_LINE_SIZE); +#endif /* CONFIG_SOC_FLASH_NRF_THROTTLING */ + if (data) { + memcpy((void *)addr, data, chunk_len); + } else { + memset((void *)addr, ERASE_VALUE, chunk_len); + } +#ifdef CONFIG_SOC_FLASH_NRF_THROTTLING + addr += chunk_len; + data = (const uint8_t *)data + chunk_len; + len -= chunk_len; + k_usleep(CONFIG_NRF_RRAM_THROTTLING_DELAY); } +#endif /* CONFIG_SOC_FLASH_NRF_THROTTLING */ barrier_dmem_fence_full(); /* Barrier following our last write. */ @@ -279,6 +297,12 @@ static int nrf_rram_read(const struct device *dev, off_t addr, void *data, size_ } addr += RRAM_START; +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER && PM_APP_ADDRESS + if (addr < PM_APP_ADDRESS) { + return soc_secure_mem_read(data, (void *)addr, len); + } +#endif + memcpy(data, (void *)addr, len); return 0; diff --git a/drivers/gpio/gpio_nrfx.c b/drivers/gpio/gpio_nrfx.c index 6ccb378e161d..fcf0b2f8d27c 100644 --- a/drivers/gpio/gpio_nrfx.c +++ b/drivers/gpio/gpio_nrfx.c @@ -12,16 +12,9 @@ #include #include #include -#include #include -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_gpio_pad_group) -#define GPIO_HAS_PAD_GROUP 1 -#else -#define GPIO_HAS_PAD_GROUP 0 -#endif - #define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance) #define GPIOTE_PROP(idx, prop) DT_PROP(GPIOTE(idx), prop) @@ -55,9 +48,6 @@ struct gpio_nrfx_cfg { uint32_t edge_sense; uint8_t port_num; nrfx_gpiote_t gpiote; -#if GPIO_HAS_PAD_GROUP - const struct device *pad_group; -#endif #if defined(GPIOTE_FEATURE_FLAG) uint32_t flags; #endif @@ -78,6 +68,34 @@ static bool has_gpiote(const struct gpio_nrfx_cfg *cfg) return cfg->gpiote.p_reg != NULL; } +#if NRF_GPIO_HAS_RETENTION_SETCLEAR + +static void port_retain_set(const struct gpio_nrfx_cfg *cfg, uint32_t mask) +{ + nrf_gpio_port_retain_enable(cfg->port, mask); +} + +static void port_retain_clear(const struct gpio_nrfx_cfg *cfg, uint32_t mask) +{ + nrf_gpio_port_retain_disable(cfg->port, mask); +} + +#else + +static void port_retain_set(const struct gpio_nrfx_cfg *cfg, uint32_t mask) +{ + ARG_UNUSED(cfg); + ARG_UNUSED(mask); +} + +static void port_retain_clear(const struct gpio_nrfx_cfg *cfg, uint32_t mask) +{ + ARG_UNUSED(cfg); + ARG_UNUSED(mask); +} + +#endif + static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags) { if (flags & GPIO_PULL_UP) { @@ -100,7 +118,6 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP(cfg->port_num, pin); nrf_gpio_pin_pull_t pull = get_pull(flags); nrf_gpio_pin_drive_t drive; - int pm_ret; switch (flags & (NRF_GPIO_DRIVE_MSK | GPIO_OPEN_DRAIN)) { case NRF_GPIO_DRIVE_S0S1: @@ -131,10 +148,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, return -EINVAL; } - ret = pm_device_runtime_get(port); - if (ret < 0) { - return ret; - } + port_retain_clear(cfg, BIT(pin)); if (flags & GPIO_OUTPUT_INIT_HIGH) { nrf_gpio_port_out_set(cfg->port, BIT(pin)); @@ -196,6 +210,8 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, err = nrfx_gpiote_output_configure(&cfg->gpiote, abs_pin, &output_config, NULL); + + port_retain_set(cfg, BIT(pin)); } else { nrfx_gpiote_input_pin_config_t input_pin_config = { .p_pull_config = &pull, @@ -223,9 +239,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, } end: - pm_ret = pm_device_runtime_put(port); - - return (ret != 0) ? ret : pm_ret; + return ret; } #ifdef CONFIG_GPIO_GET_CONFIG @@ -315,49 +329,37 @@ static int gpio_nrfx_port_set_masked_raw(const struct device *port, gpio_port_value_t value) { NRF_GPIO_Type *reg = get_port_cfg(port)->port; - int ret; const uint32_t set_mask = value & mask; const uint32_t clear_mask = (~set_mask) & mask; - ret = pm_device_runtime_get(port); - if (ret < 0) { - return ret; - } - + port_retain_clear(get_port_cfg(port), mask); nrf_gpio_port_out_set(reg, set_mask); nrf_gpio_port_out_clear(reg, clear_mask); - return pm_device_runtime_put(port); + port_retain_set(get_port_cfg(port), mask); + return 0; } static int gpio_nrfx_port_set_bits_raw(const struct device *port, gpio_port_pins_t mask) { NRF_GPIO_Type *reg = get_port_cfg(port)->port; - int ret; - - ret = pm_device_runtime_get(port); - if (ret < 0) { - return ret; - } + port_retain_clear(get_port_cfg(port), mask); nrf_gpio_port_out_set(reg, mask); - return pm_device_runtime_put(port); + port_retain_set(get_port_cfg(port), mask); + return 0; } static int gpio_nrfx_port_clear_bits_raw(const struct device *port, gpio_port_pins_t mask) { NRF_GPIO_Type *reg = get_port_cfg(port)->port; - int ret; - - ret = pm_device_runtime_get(port); - if (ret < 0) { - return ret; - } + port_retain_clear(get_port_cfg(port), mask); nrf_gpio_port_out_clear(reg, mask); - return pm_device_runtime_put(port); + port_retain_set(get_port_cfg(port), mask); + return 0; } static int gpio_nrfx_port_toggle_bits(const struct device *port, @@ -367,16 +369,12 @@ static int gpio_nrfx_port_toggle_bits(const struct device *port, const uint32_t value = nrf_gpio_port_out_read(reg) ^ mask; const uint32_t set_mask = value & mask; const uint32_t clear_mask = (~value) & mask; - int ret; - - ret = pm_device_runtime_get(port); - if (ret < 0) { - return ret; - } + port_retain_clear(get_port_cfg(port), mask); nrf_gpio_port_out_set(reg, set_mask); nrf_gpio_port_out_clear(reg, clear_mask); - return pm_device_runtime_put(port); + port_retain_set(get_port_cfg(port), mask); + return 0; } #ifdef CONFIG_GPIO_NRFX_INTERRUPT @@ -580,47 +578,11 @@ static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin, IRQ_CONNECT(DT_IRQN(node_id), DT_IRQ(node_id, priority), nrfx_isr, \ NRFX_CONCAT(nrfx_gpiote_, DT_PROP(node_id, instance), _irq_handler), 0); -static int gpio_nrfx_pm_suspend(const struct device *port) +static int gpio_nrfx_pm_hook(const struct device *port, enum pm_device_action action) { -#if GPIO_HAS_PAD_GROUP - const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); - - return pm_device_runtime_put(cfg->pad_group); -#else ARG_UNUSED(port); + ARG_UNUSED(action); return 0; -#endif -} - -static int gpio_nrfx_pm_resume(const struct device *port) -{ -#if GPIO_HAS_PAD_GROUP - const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); - - return pm_device_runtime_get(cfg->pad_group); -#else - ARG_UNUSED(port); - return 0; -#endif -} - -static int gpio_nrfx_pm_hook(const struct device *port, enum pm_device_action action) -{ - int ret; - - switch (action) { - case PM_DEVICE_ACTION_SUSPEND: - ret = gpio_nrfx_pm_suspend(port); - break; - case PM_DEVICE_ACTION_RESUME: - ret = gpio_nrfx_pm_resume(port); - break; - default: - ret = -ENOTSUP; - break; - } - - return ret; } static int gpio_nrfx_init(const struct device *port) @@ -687,13 +649,6 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = { "Please enable GPIOTE instance for used GPIO port!")), \ ()) -#if GPIO_HAS_PAD_GROUP -#define GPIO_NRF_PAD_GROUP_INIT(id) \ - .pad_group = DEVICE_DT_GET(DT_INST_CHILD(id, pad_group)), -#else -#define GPIO_NRF_PAD_GROUP_INIT(id) -#endif - #define GPIO_NRF_DEVICE(id) \ GPIOTE_CHECK(id); \ static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \ @@ -705,7 +660,6 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = { .port_num = DT_INST_PROP(id, port), \ .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \ .gpiote = GPIOTE_INSTANCE(id), \ - GPIO_NRF_PAD_GROUP_INIT(id) \ IF_ENABLED(GPIOTE_FEATURE_FLAG, \ (.flags = \ (DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ? \ diff --git a/drivers/i2c/i2c_nrfx_twim.c b/drivers/i2c/i2c_nrfx_twim.c index e3c307231ab1..bc26bf841124 100644 --- a/drivers/i2c/i2c_nrfx_twim.c +++ b/drivers/i2c/i2c_nrfx_twim.c @@ -285,7 +285,7 @@ static DEVICE_API(i2c, i2c_nrfx_twim_driver_api) = { DT_PROP(I2C(idx), easydma_maxcnt_bits)), \ }; \ PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, \ - PM_DEVICE_ISR_SAFE); \ + I2C_PM_ISR_SAFE(idx)); \ I2C_DEVICE_DT_DEINIT_DEFINE(I2C(idx), \ i2c_nrfx_twim_init, \ i2c_nrfx_twim_deinit, \ diff --git a/drivers/i2c/i2c_nrfx_twim_common.h b/drivers/i2c/i2c_nrfx_twim_common.h index 3c5c82311bae..d476ba3f05ff 100644 --- a/drivers/i2c/i2c_nrfx_twim_common.h +++ b/drivers/i2c/i2c_nrfx_twim_common.h @@ -31,6 +31,26 @@ extern "C" { #define I2C_FREQUENCY(idx) I2C_NRFX_TWIM_FREQUENCY(DT_PROP_OR(I2C(idx), clock_frequency, \ I2C_BITRATE_STANDARD)) +/* Macro determines PM actions interrupt safety level. + * + * Requesting/releasing TWIM device may be ISR safe, but it cannot be reliably known whether + * managing its power domain is. It is then assumed that if power domains are used, device is + * no longer ISR safe. This macro let's us check if we will be requesting/releasing + * power domains and determines PM device ISR safety value. + */ +#define I2C_PM_ISR_SAFE(idx) \ + COND_CODE_1( \ + UTIL_AND( \ + IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN), \ + UTIL_AND( \ + DT_NODE_HAS_PROP(I2C(idx), power_domains), \ + DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE(I2C(idx), power_domains)) \ + ) \ + ), \ + (0), \ + (PM_DEVICE_ISR_SAFE) \ + ) + struct i2c_nrfx_twim_common_config { nrfx_twim_t twim; nrfx_twim_config_t twim_config; diff --git a/drivers/i2c/i2c_nrfx_twim_rtio.c b/drivers/i2c/i2c_nrfx_twim_rtio.c index 0ddf5ffdd777..7326deaafb03 100644 --- a/drivers/i2c/i2c_nrfx_twim_rtio.c +++ b/drivers/i2c/i2c_nrfx_twim_rtio.c @@ -287,7 +287,7 @@ static int i2c_nrfx_twim_rtio_deinit(const struct device *dev) }, \ .ctx = &_i2c##idx##_twim_rtio, \ }; \ - PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, PM_DEVICE_ISR_SAFE); \ + PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, I2C_PM_ISR_SAFE(idx)); \ I2C_DEVICE_DT_DEINIT_DEFINE(I2C(idx), i2c_nrfx_twim_rtio_init, i2c_nrfx_twim_rtio_deinit, \ PM_DEVICE_DT_GET(I2C(idx)), &twim_##idx##z_data, \ &twim_##idx##z_config, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ diff --git a/drivers/i2c/i2c_nrfx_twis.c b/drivers/i2c/i2c_nrfx_twis.c index be55c851f3a7..0fd9b667d23c 100644 --- a/drivers/i2c/i2c_nrfx_twis.c +++ b/drivers/i2c/i2c_nrfx_twis.c @@ -10,7 +10,7 @@ #include #include #include - +#include #include #include diff --git a/drivers/i2s/i2s_nrf_tdm.c b/drivers/i2s/i2s_nrf_tdm.c index 45e5b3d18049..07c561b77503 100644 --- a/drivers/i2s/i2s_nrf_tdm.c +++ b/drivers/i2s/i2s_nrf_tdm.c @@ -10,12 +10,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include LOG_MODULE_REGISTER(tdm_nrf, CONFIG_I2S_LOG_LEVEL); @@ -46,11 +48,13 @@ LOG_MODULE_REGISTER(tdm_nrf, CONFIG_I2S_LOG_LEVEL); #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(audiopll)) #define NODE_ACLK DT_NODELABEL(audiopll) #define ACLK_FREQUENCY DT_PROP_OR(NODE_ACLK, frequency, 0) - -static const struct device *audiopll = DEVICE_DT_GET(NODE_ACLK); -static const struct nrf_clock_spec aclk_spec = { - .frequency = ACLK_FREQUENCY, -}; +#elif DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(audio_auxpll)) +#define NODE_AUDIO_AUXPLL DT_NODELABEL(audio_auxpll) +#define ACLK_NORDIC_FREQUENCY DT_PROP(NODE_AUDIO_AUXPLL, nordic_frequency) +BUILD_ASSERT((ACLK_NORDIC_FREQUENCY == NRF_AUXPLL_FREQ_DIV_AUDIO_48K) || + (ACLK_NORDIC_FREQUENCY == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1), + "Unsupported Audio AUXPLL frequency selection for TDM"); +#define ACLK_FREQUENCY CLOCK_CONTROL_NRF_AUXPLL_GET_FREQ(NODE_AUDIO_AUXPLL) #elif DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(aclk)) #define NODE_ACLK DT_NODELABEL(aclk) #define ACLK_FREQUENCY DT_PROP_OR(NODE_ACLK, clock_frequency, 0) @@ -106,7 +110,10 @@ struct tdm_drv_cfg { }; struct tdm_drv_data { -#if CONFIG_CLOCK_CONTROL_NRF +#if CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL || DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) + const struct device *audiopll; + struct nrf_clock_spec aclk_spec; +#elif CONFIG_CLOCK_CONTROL_NRF struct onoff_manager *clk_mgr; #endif struct onoff_client clk_cli; @@ -131,8 +138,10 @@ static int audio_clock_request(struct tdm_drv_data *drv_data) { #if DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRF return onoff_request(drv_data->clk_mgr, &drv_data->clk_cli); -#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL - return nrf_clock_control_request(audiopll, &aclk_spec, &drv_data->clk_cli); +#elif (DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL) || \ + DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) + return nrf_clock_control_request(drv_data->audiopll, &drv_data->aclk_spec, + &drv_data->clk_cli); #else (void)drv_data; @@ -144,10 +153,9 @@ static int audio_clock_release(struct tdm_drv_data *drv_data) { #if DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRF return onoff_release(drv_data->clk_mgr); -#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL - (void)drv_data; - - return nrf_clock_control_release(audiopll, &aclk_spec); +#elif (DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL) || \ + DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) + return nrf_clock_control_release(drv_data->audiopll, &drv_data->aclk_spec); #else (void)drv_data; @@ -1119,6 +1127,16 @@ static void clock_manager_init(const struct device *dev) subsys = CLOCK_CONTROL_NRF_SUBSYS_HFAUDIO; drv_data->clk_mgr = z_nrf_clock_control_get_onoff(subsys); __ASSERT_NO_MSG(drv_data->clk_mgr != NULL); +#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL + struct tdm_drv_data *drv_data = dev->data; + + drv_data->audiopll = DEVICE_DT_GET(NODE_ACLK); + drv_data->aclk_spec.frequency = ACLK_FREQUENCY; +#elif DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) + struct tdm_drv_data *drv_data = dev->data; + + drv_data->audiopll = DEVICE_DT_GET(NODE_AUDIO_AUXPLL); + drv_data->aclk_spec.frequency = ACLK_FREQUENCY; #else (void)dev; #endif @@ -1193,9 +1211,10 @@ static DEVICE_API(i2s, tdm_nrf_drv_api) = { clock_manager_init(dev); \ return 0; \ } \ - BUILD_ASSERT((TDM_SCK_CLK_SRC(idx) != ACLK && TDM_MCK_CLK_SRC(idx) != ACLK) || \ - DT_NODE_HAS_STATUS_OKAY(NODE_ACLK), \ - "Clock source ACLK requires the audiopll node."); \ + BUILD_ASSERT((TDM_SCK_CLK_SRC(idx) != ACLK && TDM_MCK_CLK_SRC(idx) != ACLK) || \ + (DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) || \ + DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL)), \ + "Clock source ACLK requires the audiopll/audio_auxpll node."); \ NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(TDM(idx)); \ DEVICE_DT_DEFINE(TDM(idx), tdm_nrf_init##idx, NULL, &tdm_nrf_data##idx, &tdm_nrf_cfg##idx, \ POST_KERNEL, CONFIG_I2S_INIT_PRIORITY, &tdm_nrf_drv_api); diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index aa67a1f99e15..60f45edb9c79 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -499,7 +499,9 @@ static bool nrf5_tx_immediate(struct net_pkt *pkt, uint8_t *payload, bool cca) }, }; - return nrf_802154_transmit_raw(payload, &metadata); + nrf_802154_tx_error_t result = nrf_802154_transmit_raw(payload, &metadata); + + return result == NRF_802154_TX_ERROR_NONE; } #if NRF_802154_CSMA_CA_ENABLED @@ -516,7 +518,9 @@ static bool nrf5_tx_csma_ca(struct net_pkt *pkt, uint8_t *payload) }, }; - return nrf_802154_transmit_csma_ca_raw(payload, &metadata); + nrf_802154_tx_error_t result = nrf_802154_transmit_csma_ca_raw(payload, &metadata); + + return result == NRF_802154_TX_ERROR_NONE; } #endif @@ -573,7 +577,9 @@ static bool nrf5_tx_at(struct nrf5_802154_data *nrf5_radio, struct net_pkt *pkt, uint64_t tx_at = nrf_802154_timestamp_phr_to_shr_convert( net_pkt_timestamp_ns(pkt) / NSEC_PER_USEC); - return nrf_802154_transmit_raw_at(payload, tx_at, &metadata); + nrf_802154_tx_error_t result = nrf_802154_transmit_raw_at(payload, tx_at, &metadata); + + return result == NRF_802154_TX_ERROR_NONE; } #endif /* CONFIG_NET_PKT_TXTIME */ diff --git a/drivers/misc/CMakeLists.txt b/drivers/misc/CMakeLists.txt index 437bd124247a..8426090ab14e 100644 --- a/drivers/misc/CMakeLists.txt +++ b/drivers/misc/CMakeLists.txt @@ -15,5 +15,4 @@ add_subdirectory_ifdef(CONFIG_RENESAS_RX_EXTERNAL_INTERRUPT renesas_rx_external_ add_subdirectory_ifdef(CONFIG_NXP_RTXXX_DSP_CTRL nxp_rtxxx_dsp_ctrl) add_subdirectory_ifdef(CONFIG_STM32N6_AXISRAM stm32n6_axisram) -add_subdirectory(coresight) add_subdirectory(interconn) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 6d4d5cfc16fe..0a3af14dc2c0 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -15,7 +15,6 @@ source "drivers/misc/timeaware_gpio/Kconfig" source "drivers/misc/devmux/Kconfig" source "drivers/misc/nordic_vpr_launcher/Kconfig" source "drivers/misc/mcux_flexio/Kconfig" -source "drivers/misc/coresight/Kconfig" source "drivers/misc/interconn/Kconfig" source "drivers/misc/renesas_ra_external_interrupt/Kconfig" source "drivers/misc/renesas_rx_external_interrupt/Kconfig" diff --git a/drivers/misc/coresight/CMakeLists.txt b/drivers/misc/coresight/CMakeLists.txt deleted file mode 100644 index 1ec34ca2f75a..000000000000 --- a/drivers/misc/coresight/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources_ifdef(CONFIG_NRF_ETR nrf_etr.c) diff --git a/drivers/misc/nordic_vpr_launcher/Kconfig b/drivers/misc/nordic_vpr_launcher/Kconfig index d00bcc583f96..edd2a9ead753 100644 --- a/drivers/misc/nordic_vpr_launcher/Kconfig +++ b/drivers/misc/nordic_vpr_launcher/Kconfig @@ -18,6 +18,7 @@ source "subsys/logging/Kconfig.template.log_config" config NORDIC_VPR_LAUNCHER_INIT_PRIORITY int "Nordic VPR coprocessor launcher init priority" + default 44 if DT_HAS_NORDIC_CORESIGHT_NRF_ENABLED default 0 help The init priority of the VPR coprocessor launcher. diff --git a/drivers/modem/CMakeLists.txt b/drivers/modem/CMakeLists.txt index 62b84bd79294..adc6614dc7fe 100644 --- a/drivers/modem/CMakeLists.txt +++ b/drivers/modem/CMakeLists.txt @@ -36,4 +36,5 @@ if (CONFIG_MODEM_SIM7080) endif() zephyr_library_sources_ifdef(CONFIG_MODEM_CELLULAR modem_cellular.c) +zephyr_library_sources_ifdef(CONFIG_MODEM_AT_USER_PIPE modem_at_user_pipe.c) zephyr_library_sources_ifdef(CONFIG_MODEM_AT_SHELL modem_at_shell.c) diff --git a/drivers/modem/Kconfig.at_shell b/drivers/modem/Kconfig.at_shell index b2f6f42e3936..3d399e2338ce 100644 --- a/drivers/modem/Kconfig.at_shell +++ b/drivers/modem/Kconfig.at_shell @@ -1,22 +1,30 @@ # Copyright (c) 2024 Trackunit Corporation # SPDX-License-Identifier: Apache-2.0 -config MODEM_AT_SHELL - bool "AT command shell based on modem modules" - select MODEM_MODULES +config MODEM_AT_USER_PIPE + bool "Modem AT command user pipe helpers" + depends on $(dt_alias_enabled,modem) select MODEM_CHAT select MODEM_PIPE select MODEM_PIPELINK + help + Utility functions for managing access to user pipes + for arbitrary AT commands + +config MODEM_AT_USER_PIPE_IDX + int "User pipe number to use" + depends on MODEM_AT_USER_PIPE + default 0 + +config MODEM_AT_SHELL + bool "AT command shell based on modem modules" + select MODEM_MODULES + select MODEM_AT_USER_PIPE depends on !MODEM_SHELL depends on !SHELL_WILDCARD - depends on $(dt_alias_enabled,modem) if MODEM_AT_SHELL -config MODEM_AT_SHELL_USER_PIPE - int "User pipe number to use" - default 0 - config MODEM_AT_SHELL_RESPONSE_TIMEOUT_S int "Timeout waiting for response to AT command in seconds" default 5 diff --git a/drivers/modem/modem_at_shell.c b/drivers/modem/modem_at_shell.c index 5d2820d7483e..7d1930b6b04b 100644 --- a/drivers/modem/modem_at_shell.c +++ b/drivers/modem/modem_at_shell.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -13,17 +14,6 @@ #include LOG_MODULE_REGISTER(modem_at_shell, CONFIG_MODEM_LOG_LEVEL); -#define AT_SHELL_MODEM_NODE DT_ALIAS(modem) -#define AT_SHELL_PIPELINK_NAME _CONCAT(user_pipe_, CONFIG_MODEM_AT_SHELL_USER_PIPE) - -#define AT_SHELL_STATE_ATTACHED_BIT 0 -#define AT_SHELL_STATE_SCRIPT_RUNNING_BIT 1 - -MODEM_PIPELINK_DT_DECLARE(AT_SHELL_MODEM_NODE, AT_SHELL_PIPELINK_NAME); - -static struct modem_pipelink *at_shell_pipelink = - MODEM_PIPELINK_DT_GET(AT_SHELL_MODEM_NODE, AT_SHELL_PIPELINK_NAME); - static struct modem_chat at_shell_chat; static uint8_t at_shell_chat_receive_buf[CONFIG_MODEM_AT_SHELL_CHAT_RECEIVE_BUF_SIZE]; static uint8_t *at_shell_chat_argv_buf[2]; @@ -32,10 +22,6 @@ static struct modem_chat_script_chat at_shell_script_chat[1]; static struct modem_chat_match at_shell_script_chat_matches[2]; static uint8_t at_shell_match_buf[CONFIG_MODEM_AT_SHELL_RESPONSE_MAX_SIZE]; static const struct shell *at_shell_active_shell; -static struct k_work at_shell_open_pipe_work; -static struct k_work at_shell_attach_chat_work; -static struct k_work at_shell_release_chat_work; -static atomic_t at_shell_state; static void at_shell_print_any_match(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data) @@ -74,7 +60,7 @@ static void at_shell_script_callback(struct modem_chat *chat, enum modem_chat_script_result result, void *user_data) { - atomic_clear_bit(&at_shell_state, AT_SHELL_STATE_SCRIPT_RUNNING_BIT); + modem_at_user_pipe_release(); } MODEM_CHAT_SCRIPT_DEFINE( @@ -85,83 +71,6 @@ MODEM_CHAT_SCRIPT_DEFINE( CONFIG_MODEM_AT_SHELL_RESPONSE_TIMEOUT_S ); -static void at_shell_pipe_callback(struct modem_pipe *pipe, - enum modem_pipe_event event, - void *user_data) -{ - ARG_UNUSED(user_data); - - switch (event) { - case MODEM_PIPE_EVENT_OPENED: - LOG_INF("pipe opened"); - k_work_submit(&at_shell_attach_chat_work); - break; - - default: - break; - } -} - -void at_shell_pipelink_callback(struct modem_pipelink *link, - enum modem_pipelink_event event, - void *user_data) -{ - ARG_UNUSED(user_data); - - switch (event) { - case MODEM_PIPELINK_EVENT_CONNECTED: - LOG_INF("pipe connected"); - k_work_submit(&at_shell_open_pipe_work); - break; - - case MODEM_PIPELINK_EVENT_DISCONNECTED: - LOG_INF("pipe disconnected"); - k_work_submit(&at_shell_release_chat_work); - break; - - default: - break; - } -} - -static void at_shell_open_pipe_handler(struct k_work *work) -{ - ARG_UNUSED(work); - - LOG_INF("opening pipe"); - - modem_pipe_attach(modem_pipelink_get_pipe(at_shell_pipelink), - at_shell_pipe_callback, - NULL); - - modem_pipe_open_async(modem_pipelink_get_pipe(at_shell_pipelink)); -} - -static void at_shell_attach_chat_handler(struct k_work *work) -{ - ARG_UNUSED(work); - - modem_chat_attach(&at_shell_chat, modem_pipelink_get_pipe(at_shell_pipelink)); - atomic_set_bit(&at_shell_state, AT_SHELL_STATE_ATTACHED_BIT); - LOG_INF("chat attached"); -} - -static void at_shell_release_chat_handler(struct k_work *work) -{ - ARG_UNUSED(work); - - modem_chat_release(&at_shell_chat); - atomic_clear_bit(&at_shell_state, AT_SHELL_STATE_ATTACHED_BIT); - LOG_INF("chat released"); -} - -static void at_shell_init_work(void) -{ - k_work_init(&at_shell_open_pipe_work, at_shell_open_pipe_handler); - k_work_init(&at_shell_attach_chat_work, at_shell_attach_chat_handler); - k_work_init(&at_shell_release_chat_work, at_shell_release_chat_handler); -} - static void at_shell_init_chat(void) { const struct modem_chat_config at_shell_chat_config = { @@ -204,17 +113,11 @@ static void at_shell_init_script_chat(void) CONFIG_MODEM_AT_SHELL_RESPONSE_TIMEOUT_S); } -static void at_shell_init_pipelink(void) -{ - modem_pipelink_attach(at_shell_pipelink, at_shell_pipelink_callback, NULL); -} - static int at_shell_init(void) { - at_shell_init_work(); at_shell_init_chat(); at_shell_init_script_chat(); - at_shell_init_pipelink(); + modem_at_user_pipe_init(&at_shell_chat); return 0; } @@ -228,14 +131,19 @@ static int at_shell_cmd_handler(const struct shell *sh, size_t argc, char **argv return -EINVAL; } - if (!atomic_test_bit(&at_shell_state, AT_SHELL_STATE_ATTACHED_BIT)) { - shell_error(sh, "modem is not ready"); - return -EPERM; - } - - if (atomic_test_and_set_bit(&at_shell_state, AT_SHELL_STATE_SCRIPT_RUNNING_BIT)) { - shell_error(sh, "script is already running"); - return -EBUSY; + ret = modem_at_user_pipe_claim(); + if (ret < 0) { + switch (ret) { + case -EPERM: + shell_error(sh, "modem is not ready"); + break; + case -EBUSY: + shell_error(sh, "script is already running"); + break; + default: + shell_error(sh, "unknown"); + } + return ret; } strncpy(at_shell_request_buf, argv[1], sizeof(at_shell_request_buf) - 1); @@ -260,7 +168,7 @@ static int at_shell_cmd_handler(const struct shell *sh, size_t argc, char **argv ret = modem_chat_run_script_async(&at_shell_chat, &at_shell_script); if (ret < 0) { shell_error(sh, "failed to start script"); - atomic_clear_bit(&at_shell_state, AT_SHELL_STATE_SCRIPT_RUNNING_BIT); + modem_at_user_pipe_release(); } return ret; diff --git a/drivers/modem/modem_at_user_pipe.c b/drivers/modem/modem_at_user_pipe.c new file mode 100644 index 000000000000..6fb0046f0fef --- /dev/null +++ b/drivers/modem/modem_at_user_pipe.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2025 Embeint Holdings Pty Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#define AT_UTIL_MODEM_NODE DT_ALIAS(modem) +#define AT_UTIL_PIPELINK_NAME _CONCAT(user_pipe_, CONFIG_MODEM_AT_USER_PIPE_IDX) + +#define AT_UTIL_STATE_ATTACHED_BIT 0 +#define AT_UTIL_STATE_SCRIPT_RUNNING_BIT 1 + +MODEM_PIPELINK_DT_DECLARE(AT_UTIL_MODEM_NODE, AT_UTIL_PIPELINK_NAME); + +static struct modem_pipelink *at_util_pipelink = + MODEM_PIPELINK_DT_GET(AT_UTIL_MODEM_NODE, AT_UTIL_PIPELINK_NAME); + +static struct k_work at_util_open_pipe_work; +static struct k_work at_util_attach_chat_work; +static struct k_work at_util_release_chat_work; +static struct modem_chat *at_util_chat; +static atomic_t at_util_state; + +LOG_MODULE_REGISTER(modem_at_user_pipe, CONFIG_MODEM_LOG_LEVEL); + +static void at_util_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_event event, + void *user_data) +{ + ARG_UNUSED(user_data); + + switch (event) { + case MODEM_PIPE_EVENT_OPENED: + LOG_INF("pipe opened"); + k_work_submit(&at_util_attach_chat_work); + break; + + default: + break; + } +} + +void at_util_pipelink_callback(struct modem_pipelink *link, enum modem_pipelink_event event, + void *user_data) +{ + ARG_UNUSED(user_data); + + switch (event) { + case MODEM_PIPELINK_EVENT_CONNECTED: + LOG_INF("pipe connected"); + k_work_submit(&at_util_open_pipe_work); + break; + + case MODEM_PIPELINK_EVENT_DISCONNECTED: + LOG_INF("pipe disconnected"); + k_work_submit(&at_util_release_chat_work); + break; + + default: + break; + } +} + +static void at_util_open_pipe_handler(struct k_work *work) +{ + ARG_UNUSED(work); + + LOG_INF("opening pipe"); + + modem_pipe_attach(modem_pipelink_get_pipe(at_util_pipelink), at_util_pipe_callback, NULL); + + modem_pipe_open_async(modem_pipelink_get_pipe(at_util_pipelink)); +} + +static void at_util_attach_chat_handler(struct k_work *work) +{ + ARG_UNUSED(work); + + modem_chat_attach(at_util_chat, modem_pipelink_get_pipe(at_util_pipelink)); + atomic_set_bit(&at_util_state, AT_UTIL_STATE_ATTACHED_BIT); + LOG_INF("chat attached"); +} + +static void at_util_release_chat_handler(struct k_work *work) +{ + ARG_UNUSED(work); + + modem_chat_release(at_util_chat); + atomic_clear_bit(&at_util_state, AT_UTIL_STATE_ATTACHED_BIT); + LOG_INF("chat released"); +} + +void modem_at_user_pipe_init(struct modem_chat *chat) +{ + at_util_chat = chat; + /* Initialise workers and setup callbacks */ + k_work_init(&at_util_open_pipe_work, at_util_open_pipe_handler); + k_work_init(&at_util_attach_chat_work, at_util_attach_chat_handler); + k_work_init(&at_util_release_chat_work, at_util_release_chat_handler); + modem_pipelink_attach(at_util_pipelink, at_util_pipelink_callback, NULL); +} + +int modem_at_user_pipe_claim(void) +{ + if (!atomic_test_bit(&at_util_state, AT_UTIL_STATE_ATTACHED_BIT)) { + return -EPERM; + } + + if (atomic_test_and_set_bit(&at_util_state, AT_UTIL_STATE_SCRIPT_RUNNING_BIT)) { + return -EBUSY; + } + + return 0; +} + +void modem_at_user_pipe_release(void) +{ + atomic_clear_bit(&at_util_state, AT_UTIL_STATE_SCRIPT_RUNNING_BIT); +} diff --git a/drivers/modem/modem_cellular.c b/drivers/modem/modem_cellular.c index 3e7b3a30eff1..b99401fedca5 100644 --- a/drivers/modem/modem_cellular.c +++ b/drivers/modem/modem_cellular.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include @@ -83,6 +85,7 @@ enum modem_cellular_event { MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS, MODEM_CELLULAR_EVENT_SCRIPT_FAILED, MODEM_CELLULAR_EVENT_CMUX_CONNECTED, + MODEM_CELLULAR_EVENT_CMUX_DISCONNECTED, MODEM_CELLULAR_EVENT_DLCI1_OPENED, MODEM_CELLULAR_EVENT_DLCI2_OPENED, MODEM_CELLULAR_EVENT_TIMEOUT, @@ -93,6 +96,7 @@ enum modem_cellular_event { MODEM_CELLULAR_EVENT_PPP_DEAD, MODEM_CELLULAR_EVENT_MODEM_READY, MODEM_CELLULAR_EVENT_APN_SET, + MODEM_CELLULAR_EVENT_RING, }; struct modem_cellular_event_cb { @@ -110,8 +114,8 @@ struct modem_cellular_data { /* CMUX */ struct modem_cmux cmux; - uint8_t cmux_receive_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE]; - uint8_t cmux_transmit_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE]; + uint8_t cmux_receive_buf[MODEM_CMUX_WORK_BUFFER_SIZE]; + uint8_t cmux_transmit_buf[MODEM_CMUX_WORK_BUFFER_SIZE]; struct modem_cmux_dlci dlci1; struct modem_cmux_dlci dlci2; @@ -119,9 +123,9 @@ struct modem_cellular_data { struct modem_pipe *dlci2_pipe; /* Points to dlci2_pipe or NULL. Used for shutdown script if not NULL */ struct modem_pipe *cmd_pipe; - uint8_t dlci1_receive_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE]; + uint8_t dlci1_receive_buf[MODEM_CMUX_WORK_BUFFER_SIZE]; /* DLCI 2 is only used for chat scripts. */ - uint8_t dlci2_receive_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE]; + uint8_t dlci2_receive_buf[MODEM_CMUX_WORK_BUFFER_SIZE]; /* Modem chat */ struct modem_chat chat; @@ -163,11 +167,13 @@ struct modem_cellular_data { /* Event dispatcher */ struct k_work event_dispatch_work; uint8_t event_buf[8]; - struct ring_buf event_rb; - struct k_mutex event_rb_lock; + struct k_pipe event_pipe; struct k_mutex api_lock; struct modem_cellular_event_cb cb; + + /* Ring interrupt */ + struct gpio_callback ring_gpio_cb; }; struct modem_cellular_user_pipe { @@ -184,11 +190,16 @@ struct modem_cellular_config { struct gpio_dt_spec power_gpio; struct gpio_dt_spec reset_gpio; struct gpio_dt_spec wake_gpio; + struct gpio_dt_spec ring_gpio; + struct gpio_dt_spec dtr_gpio; uint16_t power_pulse_duration_ms; uint16_t reset_pulse_duration_ms; uint16_t startup_time_ms; uint16_t shutdown_time_ms; bool autostarts; + bool cmux_enable_runtime_power_save; + bool cmux_close_pipe_on_power_save; + k_timeout_t cmux_idle_timeout; const struct modem_chat_script *init_chat_script; const struct modem_chat_script *dial_chat_script; const struct modem_chat_script *periodic_chat_script; @@ -257,6 +268,8 @@ static const char *modem_cellular_event_str(enum modem_cellular_event event) return "script failed"; case MODEM_CELLULAR_EVENT_CMUX_CONNECTED: return "cmux connected"; + case MODEM_CELLULAR_EVENT_CMUX_DISCONNECTED: + return "cmux disconnected"; case MODEM_CELLULAR_EVENT_DLCI1_OPENED: return "dlci1 opened"; case MODEM_CELLULAR_EVENT_DLCI2_OPENED: @@ -277,6 +290,8 @@ static const char *modem_cellular_event_str(enum modem_cellular_event event) return "modem ready"; case MODEM_CELLULAR_EVENT_APN_SET: return "apn set"; + case MODEM_CELLULAR_EVENT_RING: + return "RING"; } return ""; @@ -702,26 +717,18 @@ static void modem_cellular_event_dispatch_handler(struct k_work *item) struct modem_cellular_data *data = CONTAINER_OF(item, struct modem_cellular_data, event_dispatch_work); - uint8_t events[sizeof(data->event_buf)]; - uint8_t events_cnt; - - k_mutex_lock(&data->event_rb_lock, K_FOREVER); + enum modem_cellular_event event; + const size_t len = sizeof(event); - events_cnt = (uint8_t)ring_buf_get(&data->event_rb, events, sizeof(data->event_buf)); - - k_mutex_unlock(&data->event_rb_lock); - - for (uint8_t i = 0; i < events_cnt; i++) { - modem_cellular_event_handler(data, (enum modem_cellular_event)events[i]); + while (k_pipe_read(&data->event_pipe, (uint8_t *)&event, len, K_NO_WAIT) == len) { + modem_cellular_event_handler(data, (enum modem_cellular_event)event); } } static void modem_cellular_delegate_event(struct modem_cellular_data *data, enum modem_cellular_event evt) { - k_mutex_lock(&data->event_rb_lock, K_FOREVER); - ring_buf_put(&data->event_rb, (uint8_t *)&evt, 1); - k_mutex_unlock(&data->event_rb_lock); + k_pipe_write(&data->event_pipe, (const uint8_t *)&evt, sizeof(evt), K_NO_WAIT); k_work_submit(&data->event_dispatch_work); } @@ -1242,7 +1249,10 @@ static void modem_cellular_run_dial_script_event_handler(struct modem_cellular_d case MODEM_CELLULAR_EVENT_SUSPEND: modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF); break; - + case MODEM_CELLULAR_EVENT_RING: + LOG_INF("RING received!"); + modem_pipe_open_async(data->uart_pipe); + break; default: break; } @@ -1287,7 +1297,10 @@ static void modem_cellular_await_registered_event_handler(struct modem_cellular_ case MODEM_CELLULAR_EVENT_SUSPEND: modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF); break; - + case MODEM_CELLULAR_EVENT_RING: + LOG_INF("RING received!"); + modem_pipe_open_async(data->uart_pipe); + break; default: break; } @@ -1332,7 +1345,10 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data * modem_ppp_release(data->ppp); modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_INIT_POWER_OFF); break; - + case MODEM_CELLULAR_EVENT_RING: + LOG_INF("RING received!"); + modem_pipe_open_async(data->uart_pipe); + break; default: break; } @@ -1377,6 +1393,7 @@ static int modem_cellular_on_dormant_state_leave(struct modem_cellular_data *dat static int modem_cellular_on_init_power_off_state_enter(struct modem_cellular_data *data) { + modem_cmux_disconnect_async(&data->cmux); modem_cellular_start_timer(data, K_MSEC(2000)); return 0; } @@ -1388,6 +1405,9 @@ static void modem_cellular_init_power_off_event_handler(struct modem_cellular_da (const struct modem_cellular_config *)data->dev->config; switch (evt) { + case MODEM_CELLULAR_EVENT_CMUX_DISCONNECTED: + modem_cellular_stop_timer(data); + __fallthrough; case MODEM_CELLULAR_EVENT_TIMEOUT: /* Shutdown script can only be used if cmd_pipe is available, i.e. we are not in * some intermediary state without a pipe for commands available @@ -1775,7 +1795,9 @@ static void modem_cellular_cmux_handler(struct modem_cmux *cmux, enum modem_cmux case MODEM_CMUX_EVENT_CONNECTED: modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_CMUX_CONNECTED); break; - + case MODEM_CMUX_EVENT_DISCONNECTED: + modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_CMUX_DISCONNECTED); + break; default: break; } @@ -2063,6 +2085,15 @@ static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint64_t } } +static void modem_cellular_ring_gpio_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) +{ + struct modem_cellular_data *data = + CONTAINER_OF(cb, struct modem_cellular_data, ring_gpio_cb); + + modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RING); +} + static void modem_cellular_init_apn(struct modem_cellular_data *data) { #ifdef CONFIG_MODEM_CELLULAR_APN @@ -2086,14 +2117,14 @@ static int modem_cellular_init(const struct device *dev) { struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data; struct modem_cellular_config *config = (struct modem_cellular_config *)dev->config; + const struct gpio_dt_spec *dtr_gpio = NULL; data->dev = dev; k_mutex_init(&data->api_lock); k_work_init_delayable(&data->timeout_work, modem_cellular_timeout_handler); - k_work_init(&data->event_dispatch_work, modem_cellular_event_dispatch_handler); - ring_buf_init(&data->event_rb, sizeof(data->event_buf), data->event_buf); + k_pipe_init(&data->event_pipe, data->event_buf, sizeof(data->event_buf)); k_sem_init(&data->suspended_sem, 0, 1); @@ -2109,9 +2140,42 @@ static int modem_cellular_init(const struct device *dev) gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_ACTIVE); } + if (modem_cellular_gpio_is_enabled(&config->ring_gpio)) { + int ret; + + ret = gpio_pin_configure_dt(&config->ring_gpio, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Failed to configure ring GPIO (%d)", ret); + return ret; + } + + gpio_init_callback(&data->ring_gpio_cb, modem_cellular_ring_gpio_callback, + BIT(config->ring_gpio.pin)); + + ret = gpio_add_callback(config->ring_gpio.port, &data->ring_gpio_cb); + if (ret < 0) { + LOG_ERR("Failed to add ring GPIO callback (%d)", ret); + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&config->ring_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + LOG_ERR("Failed to configure ring GPIO interrupt (%d)", ret); + return ret; + } + + LOG_DBG("Ring GPIO interrupt configured"); + } + + if (modem_cellular_gpio_is_enabled(&config->dtr_gpio)) { + gpio_pin_configure_dt(&config->dtr_gpio, GPIO_OUTPUT_INACTIVE); + dtr_gpio = &config->dtr_gpio; + } + { const struct modem_backend_uart_config uart_backend_config = { .uart = config->uart, + .dtr_gpio = dtr_gpio, .receive_buf = data->uart_backend_receive_buf, .receive_buf_size = ARRAY_SIZE(data->uart_backend_receive_buf), .transmit_buf = data->uart_backend_transmit_buf, @@ -2132,6 +2196,9 @@ static int modem_cellular_init(const struct device *dev) .receive_buf_size = ARRAY_SIZE(data->cmux_receive_buf), .transmit_buf = data->cmux_transmit_buf, .transmit_buf_size = ARRAY_SIZE(data->cmux_transmit_buf), + .enable_runtime_power_management = config->cmux_enable_runtime_power_save, + .close_pipe_on_power_save = config->cmux_close_pipe_on_power_save, + .idle_timeout = config->cmux_idle_timeout, }; modem_cmux_init(&data->cmux, &cmux_config); @@ -2749,6 +2816,7 @@ MODEM_CHAT_SCRIPT_DEFINE(telit_me310g1_shutdown_chat_script, #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf91_slm) MODEM_CHAT_SCRIPT_CMDS_DEFINE(nordic_nrf91_slm_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT", allow_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), @@ -2766,19 +2834,15 @@ MODEM_CHAT_SCRIPT_DEFINE(nordic_nrf91_slm_init_chat_script, nordic_nrf91_slm_ini abort_matches, modem_cellular_chat_callback_handler, 10); MODEM_CHAT_SCRIPT_CMDS_DEFINE(nordic_nrf91_slm_dial_chat_script_cmds, - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match), + MODEM_CHAT_SCRIPT_CMD_RESP("AT#XPPP=1", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match), MODEM_CHAT_SCRIPT_CMD_RESP("AT#XCMUX=2", ok_match)); MODEM_CHAT_SCRIPT_DEFINE(nordic_nrf91_slm_dial_chat_script, nordic_nrf91_slm_dial_chat_script_cmds, dial_abort_matches, modem_cellular_chat_callback_handler, 10); -MODEM_CHAT_SCRIPT_CMDS_DEFINE(nordic_nrf91_slm_periodic_chat_script_cmds, - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match)); +MODEM_CHAT_SCRIPT_EMPTY_DEFINE(nordic_nrf91_slm_periodic_chat_script); -MODEM_CHAT_SCRIPT_DEFINE(nordic_nrf91_slm_periodic_chat_script, - nordic_nrf91_slm_periodic_chat_script_cmds, abort_matches, - modem_cellular_chat_callback_handler, 4); #endif #if DT_HAS_COMPAT_STATUS_OKAY(sqn_gm02s) @@ -2873,26 +2937,30 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, /* Helper to define modem instance */ #define MODEM_CELLULAR_DEFINE_INSTANCE(inst, power_ms, reset_ms, startup_ms, shutdown_ms, start, \ - set_baudrate_script, \ - init_script, \ - dial_script, \ - periodic_script, \ - shutdown_script) \ + set_baudrate_script, init_script, dial_script, \ + periodic_script, shutdown_script) \ static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ .wake_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_wake_gpios, {}), \ + .ring_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_ring_gpios, {}), \ + .dtr_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_dtr_gpios, {}), \ .power_pulse_duration_ms = (power_ms), \ .reset_pulse_duration_ms = (reset_ms), \ - .startup_time_ms = (startup_ms), \ + .startup_time_ms = (startup_ms), \ .shutdown_time_ms = (shutdown_ms), \ .autostarts = DT_INST_PROP_OR(inst, autostarts, (start)), \ - .set_baudrate_chat_script = (set_baudrate_script), \ - .init_chat_script = (init_script), \ - .dial_chat_script = (dial_script), \ + .cmux_enable_runtime_power_save = \ + DT_INST_PROP_OR(inst, cmux_enable_runtime_power_save, 0), \ + .cmux_close_pipe_on_power_save = \ + DT_INST_PROP_OR(inst, cmux_close_pipe_on_power_save, 0), \ + .cmux_idle_timeout = K_MSEC(DT_INST_PROP_OR(inst, cmux_idle_timeout_ms, 0)), \ + .set_baudrate_chat_script = (set_baudrate_script), \ + .init_chat_script = (init_script), \ + .dial_chat_script = (dial_script), \ .periodic_chat_script = (periodic_script), \ - .shutdown_chat_script = (shutdown_script), \ + .shutdown_chat_script = (shutdown_script), \ .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ @@ -2905,7 +2973,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &modem_cellular_api); #define MODEM_CELLULAR_DEVICE_QUECTEL_BG9X(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -2925,7 +2993,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &quectel_bg9x_shutdown_chat_script) #define MODEM_CELLULAR_DEVICE_QUECTEL_EG25_G(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -2944,7 +3012,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &quectel_eg25_g_periodic_chat_script, NULL) #define MODEM_CELLULAR_DEVICE_QUECTEL_EG800Q(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -2963,7 +3031,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &quectel_eg800q_periodic_chat_script, NULL) #define MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -2982,7 +3050,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &simcom_sim7080_periodic_chat_script, NULL) #define MODEM_CELLULAR_DEVICE_SIMCOM_A76XX(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -3002,7 +3070,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &simcom_a76xx_shutdown_chat_script) #define MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -3021,7 +3089,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &u_blox_sara_r4_periodic_chat_script, NULL) #define MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R5(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -3040,7 +3108,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &u_blox_sara_r5_periodic_chat_script, NULL) #define MODEM_CELLULAR_DEVICE_U_BLOX_LARA_R6(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -3060,7 +3128,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, NULL) #define MODEM_CELLULAR_DEVICE_SWIR_HL7800(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -3079,7 +3147,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &swir_hl7800_periodic_chat_script, NULL) #define MODEM_CELLULAR_DEVICE_TELIT_ME910G1(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -3098,7 +3166,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, NULL) #define MODEM_CELLULAR_DEVICE_TELIT_ME310G1(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ @@ -3117,7 +3185,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &telit_me310g1_shutdown_chat_script) #define MODEM_CELLULAR_DEVICE_NORDIC_NRF91_SLM(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 1500); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 1500); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r\n", \ @@ -3131,10 +3199,11 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, NULL, \ &nordic_nrf91_slm_init_chat_script, \ &nordic_nrf91_slm_dial_chat_script, \ - &nordic_nrf91_slm_periodic_chat_script, NULL) + &nordic_nrf91_slm_periodic_chat_script, \ + NULL) #define MODEM_CELLULAR_DEVICE_SQN_GM02S(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_DT_INST_PPP_DEFINE(inst, MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ .chat_delimiter = "\r", \ diff --git a/drivers/mspi/Kconfig b/drivers/mspi/Kconfig index 269d8d16f04a..a6442c1f70fe 100644 --- a/drivers/mspi/Kconfig +++ b/drivers/mspi/Kconfig @@ -55,6 +55,12 @@ config MSPI_TIMING Enables mspi_timing_config calls in device drivers for those controllers that need this to proper function at high frequencies. +config MSPI_DMA + bool "DMA support" + help + Enables DMA capabilities, depending on the driver and hardware it + runs on. + module = MSPI module-str = mspi source "subsys/logging/Kconfig.template.log_config" diff --git a/drivers/mspi/Kconfig.dw b/drivers/mspi/Kconfig.dw index 06d2e09c8af1..e967671e4723 100644 --- a/drivers/mspi/Kconfig.dw +++ b/drivers/mspi/Kconfig.dw @@ -7,13 +7,30 @@ config MSPI_DW default y depends on DT_HAS_SNPS_DESIGNWARE_SSI_ENABLED select PINCTRL if $(dt_compat_any_has_prop,$(DT_COMPAT_SNPS_DESIGNWARE_SSI),pinctrl-0) - imply MSPI_XIP imply MSPI_TIMING if MSPI_DW +config MSPI_DW_DDR + bool "Dual Data-Rate (DDR) capabilities" + default y + help + Dual data rate is supported by some devices and requires specific + registers to be enabled in the IP. + +config MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE + bool "Handle FIFO in system workqueue" + depends on MULTITHREADING + help + When the driver does not use DMA for transferring data to/from the + SSI FIFOs, handling of those may take a significant amount of time. + It may be destructive for some applications if that time is spent + in the interrupt context. This option allows offloading the job to + the system workqueue. + config MSPI_DW_TXD_DIV int "Designware SSI TX Drive edge divisor" + depends on MSPI_DW_DDR default 4 help Division factor to apply to calculated BAUDR value when writing it @@ -22,6 +39,7 @@ config MSPI_DW_TXD_DIV config MSPI_DW_TXD_MUL int "Designware SSI TX Drive edge multiplier" + depends on MSPI_DW_DDR default 1 help Multiplication factor to apply to calculated BAUDR value when writing diff --git a/drivers/mspi/mspi_dw.c b/drivers/mspi/mspi_dw.c index 66f257839aa4..66bdf670c02d 100644 --- a/drivers/mspi/mspi_dw.c +++ b/drivers/mspi/mspi_dw.c @@ -59,22 +59,43 @@ struct mspi_dw_data { enum mspi_cpp_mode xip_cpp; #endif - uint16_t dummy_bytes; + uint32_t dummy_bytes; uint8_t bytes_to_discard; uint8_t bytes_per_frame_exp; bool standard_spi; bool suspended; +#if defined(CONFIG_MULTITHREADING) + const struct device *dev; + struct k_sem finished; /* For synchronization of API calls made from different contexts. */ struct k_sem ctx_lock; /* For locking of controller configuration. */ struct k_sem cfg_lock; + + struct k_timer async_timer; + struct k_work async_timeout_work; + struct k_work async_packet_work; + + mspi_callback_handler_t cbs[MSPI_BUS_EVENT_MAX]; + struct mspi_callback_context *cb_ctxs[MSPI_BUS_EVENT_MAX]; +#else + volatile bool finished; + bool cfg_lock; +#endif + struct mspi_xfer xfer; + +#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE) + struct k_work fifo_work; + uint32_t imr; +#endif }; struct mspi_dw_config { DEVICE_MMIO_ROM; + void *wrapper_regs; void (*irq_config)(void); uint32_t clock_frequency; #if defined(CONFIG_PINCTRL) @@ -92,8 +113,14 @@ struct mspi_dw_config { uint8_t max_queued_dummy_bytes; uint8_t tx_fifo_threshold; uint8_t rx_fifo_threshold; +#ifdef CONFIG_MSPI_DMA + uint8_t dma_tx_data_level; + uint8_t dma_rx_data_level; +#endif + void *vendor_specific_data; DECLARE_REG_ACCESS(); bool sw_multi_periph; + enum mspi_op_mode op_mode; }; /* Register access helpers. */ @@ -111,13 +138,18 @@ DEFINE_MM_REG_RD_WR(rxftlr, 0x1c) DEFINE_MM_REG_RD(txflr, 0x20) DEFINE_MM_REG_RD(rxflr, 0x24) DEFINE_MM_REG_RD(sr, 0x28) -DEFINE_MM_REG_WR(imr, 0x2c) +DEFINE_MM_REG_RD_WR(imr, 0x2c) DEFINE_MM_REG_RD(isr, 0x30) DEFINE_MM_REG_RD(risr, 0x34) DEFINE_MM_REG_RD_WR(dr, 0x60) DEFINE_MM_REG_WR(rx_sample_dly, 0xf0) DEFINE_MM_REG_WR(spi_ctrlr0, 0xf4) DEFINE_MM_REG_WR(txd_drive_edge, 0xf8) +#if defined(CONFIG_MSPI_DMA) +DEFINE_MM_REG_WR(dmacr, 0x4C) +DEFINE_MM_REG_WR(dmatdlr, 0x50) +DEFINE_MM_REG_WR(dmardlr, 0x54) +#endif #if defined(CONFIG_MSPI_XIP) DEFINE_MM_REG_WR(xip_incr_inst, 0x100) @@ -130,6 +162,100 @@ DEFINE_MM_REG_WR(xip_write_ctrl, 0x148) #include "mspi_dw_vendor_specific.h" +static int start_next_packet(const struct device *dev); +static int finalize_packet(const struct device *dev, int rc); +static int finalize_transceive(const struct device *dev, int rc); + +#if defined(CONFIG_MULTITHREADING) +/* Common function to setup callback context and call user callback */ +static void call_user_callback_with_context(const struct device *dev, + enum mspi_bus_event evt_type, + uint32_t packet_idx, + int status) +{ + struct mspi_dw_data *dev_data = dev->data; + const struct mspi_xfer_packet *packet = + &dev_data->xfer.packets[packet_idx]; + struct mspi_callback_context *cb_ctx = dev_data->cb_ctxs[evt_type]; + + if (!(packet->cb_mask & BIT(evt_type)) || + !dev_data->cbs[evt_type]) { + return; + } + + LOG_DBG("Calling user function with evt_type: %u", evt_type); + + cb_ctx->mspi_evt.evt_type = evt_type; + cb_ctx->mspi_evt.evt_data.controller = dev; + cb_ctx->mspi_evt.evt_data.dev_id = dev_data->dev_id; + cb_ctx->mspi_evt.evt_data.packet = packet; + cb_ctx->mspi_evt.evt_data.packet_idx = packet_idx; + cb_ctx->mspi_evt.evt_data.status = status; + + dev_data->cbs[evt_type](cb_ctx); +} + +static void async_timeout_timer_handler(struct k_timer *timer) +{ + struct mspi_dw_data *dev_data = + CONTAINER_OF(timer, struct mspi_dw_data, async_timer); + + /* Submit work to handle timeout in proper context */ + k_work_submit(&dev_data->async_timeout_work); +} + +static void async_timeout_work_handler(struct k_work *work) +{ + struct mspi_dw_data *dev_data = + CONTAINER_OF(work, struct mspi_dw_data, async_timeout_work); + const struct device *dev = dev_data->dev; + int rc; + + LOG_ERR("Async transfer timed out"); + + rc = finalize_packet(dev, -ETIMEDOUT); + rc = finalize_transceive(dev, rc); + + /* Call user callback with timeout error (outside of any locks) */ + call_user_callback_with_context(dev, MSPI_BUS_TIMEOUT, + dev_data->packets_done, rc); +} + +static void async_packet_work_handler(struct k_work *work) +{ + struct mspi_dw_data *dev_data = + CONTAINER_OF(work, struct mspi_dw_data, async_packet_work); + const struct device *dev = dev_data->dev; + uint32_t packet_idx = dev_data->packets_done; + int rc; + + LOG_DBG("Processing async work in thread context"); + + rc = finalize_packet(dev, 0); + if (rc >= 0) { + ++dev_data->packets_done; + if (dev_data->packets_done < dev_data->xfer.num_packet) { + LOG_DBG("Starting next packet (%d/%d)", + dev_data->packets_done + 1, + dev_data->xfer.num_packet); + + rc = start_next_packet(dev); + if (rc >= 0) { + return; + } + + ++packet_idx; + } + } + + rc = finalize_transceive(dev, rc); + call_user_callback_with_context(dev, + rc < 0 ? MSPI_BUS_ERROR + : MSPI_BUS_XFER_COMPLETE, + packet_idx, rc); +} +#endif /* defined(CONFIG_MULTITHREADING) */ + static void tx_data(const struct device *dev, const struct mspi_xfer_packet *packet) { @@ -184,22 +310,31 @@ static void tx_data(const struct device *dev, dev_data->buf_pos = (uint8_t *)buf_pos; } -static bool tx_dummy_bytes(const struct device *dev) +static bool tx_dummy_bytes(const struct device *dev, bool *repeat) { struct mspi_dw_data *dev_data = dev->data; const struct mspi_dw_config *dev_config = dev->config; uint8_t fifo_room = dev_config->max_queued_dummy_bytes - FIELD_GET(TXFLR_TXTFL_MASK, read_txflr(dev)); uint8_t rx_fifo_items = FIELD_GET(RXFLR_RXTFL_MASK, read_rxflr(dev)); - uint16_t dummy_bytes = dev_data->dummy_bytes; + uint32_t dummy_bytes = dev_data->dummy_bytes; const uint8_t dummy_val = 0; /* Subtract the number of items that are already stored in the RX * FIFO to avoid overflowing it; `max_queued_dummy_bytes` accounts * that one byte that can be partially received, thus not included * in the value from the RXFLR register. + * This check also handles the case when the function is called but + * the TX FIFO is already filled up (fifo_room == 0). */ if (fifo_room <= rx_fifo_items) { + if (repeat) { + /* If no dummy bytes can be sent now, there is no point + * in repeating the loop that reads the RX FIFO. + */ + *repeat = false; + } + return false; } fifo_room -= rx_fifo_items; @@ -218,6 +353,8 @@ static bool tx_dummy_bytes(const struct device *dev) write_dr(dev, dummy_val); } while (--dummy_bytes); + dev_data->dummy_bytes = 0; + /* Set the TX start level to 0, so that the transmission will be * started now if it hasn't been yet. The threshold value is also * set to 0 here, but it doesn't really matter, as the interrupt @@ -237,9 +374,12 @@ static bool read_rx_fifo(const struct device *dev, uint8_t *buf_pos = dev_data->buf_pos; const uint8_t *buf_end = &packet->data_buf[packet->num_bytes]; uint8_t bytes_per_frame_exp = dev_data->bytes_per_frame_exp; - /* See `room` in tx_data(). */ - uint32_t in_fifo = 1; uint32_t remaining_frames; + uint32_t in_fifo = FIELD_GET(RXFLR_RXTFL_MASK, read_rxflr(dev)); + + if (in_fifo == 0) { + return false; + } do { uint32_t data = read_dr(dev); @@ -280,7 +420,34 @@ static bool read_rx_fifo(const struct device *dev, return false; } -static void mspi_dw_isr(const struct device *dev) +static inline void set_imr(const struct device *dev, uint32_t imr) +{ +#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE) + struct mspi_dw_data *dev_data = dev->data; + + dev_data->imr = imr; +#else + write_imr(dev, imr); +#endif +} + +static void handle_end_of_packet(struct mspi_dw_data *dev_data) + +{ +#if defined(CONFIG_MULTITHREADING) + if (dev_data->xfer.async) { + k_timer_stop(&dev_data->async_timer); + + k_work_submit(&dev_data->async_packet_work); + } else { + k_sem_give(&dev_data->finished); + } +#else + dev_data->finished = true; +#endif +} + +static void handle_fifos(const struct device *dev) { struct mspi_dw_data *dev_data = dev->data; const struct mspi_xfer_packet *packet = @@ -302,42 +469,116 @@ static void mspi_dw_isr(const struct device *dev) finished = true; } } else { - uint32_t int_status = read_isr(dev); + bool repeat = true; do { - if (int_status & ISR_RXFIS_BIT) { - if (read_rx_fifo(dev, packet)) { - finished = true; - break; - } + /* Always read everything from the RX FIFO, regardless + * of the interrupt status. + * tx_dummy_bytes() subtracts the number of items that + * are present in the RX FIFO from the number of dummy + * bytes it is allowed to send, so it can potentially + * not fill the TX FIFO above its transfer start level + * in some iteration of this loop. If in such case the + * interrupt handler exited without emptying the RX FIFO + * (seeing the RXFIS flag not set due to not enough + * items in the RX FIFO), this could lead to a situation + * in which a transfer stopped temporarily (after the TX + * FIFO got empty) is not resumed (since the TX FIFO is + * not filled above its transfer start level), so no + * further dummy bytes are transmitted and the RX FIFO + * has no chance to get new entries, hence no further + * interrupts are generated and the transfer gets stuck. + */ + if (read_rx_fifo(dev, packet)) { + finished = true; + break; + } - if (read_risr(dev) & RISR_RXOIR_BIT) { - finished = true; - break; - } + /* Use RISR, not ISR, because when this function is + * executed through the system workqueue, all interrupts + * are masked (IMR is 0). + */ + uint32_t int_status = read_risr(dev); - int_status = read_isr(dev); + if (int_status & RISR_RXOIR_BIT) { + finished = true; + break; } - if (int_status & ISR_TXEIS_BIT) { - if (tx_dummy_bytes(dev)) { - /* All the required dummy bytes were - * written to the FIFO; disable the TXE - * interrupt, as it's no longer needed. - */ - write_imr(dev, IMR_RXFIM_BIT); - } + /* If there are still some dummy bytes to transmit, + * always try to put some into the TX FIFO, no matter + * what's the TXE interrupt status - the TX FIFO may be + * filled above its threshold level (then its interrupt + * flag is not set), but below its transfer start level, + * so the controller may be waiting for more items to + * appear there. + */ + if (dev_data->dummy_bytes == 0) { + break; + } - int_status = read_isr(dev); + if (tx_dummy_bytes(dev, &repeat)) { + /* All the required dummy bytes were written + * to the FIFO; disable the TXE interrupt, + * as it's no longer needed. + */ + set_imr(dev, IMR_RXFIM_BIT); } - } while (int_status != 0); + + /* Repeat the loop only if any dummy bytes were sent. */ + } while (repeat); } if (finished) { - write_imr(dev, 0); + set_imr(dev, 0); + + handle_end_of_packet(dev_data); - k_sem_give(&dev_data->finished); } +} + +#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE) +static void fifo_work_handler(struct k_work *work) +{ + struct mspi_dw_data *dev_data = + CONTAINER_OF(work, struct mspi_dw_data, fifo_work); + const struct device *dev = dev_data->dev; + + handle_fifos(dev); + + write_imr(dev, dev_data->imr); +} +#endif + +static void mspi_dw_isr(const struct device *dev) +{ +#if defined(CONFIG_MSPI_DMA) + struct mspi_dw_data *dev_data = dev->data; + + if (dev_data->xfer.xfer_mode == MSPI_DMA) { + if (vendor_specific_read_dma_irq(dev)) { + set_imr(dev, 0); + handle_end_of_packet(dev_data); + } + vendor_specific_irq_clear(dev); + return; + } +#endif + +#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE) + struct mspi_dw_data *dev_data = dev->data; + int rc; + + dev_data->imr = read_imr(dev); + write_imr(dev, 0); + + rc = k_work_submit(&dev_data->fifo_work); + if (rc < 0) { + LOG_ERR("k_work_submit failed: %d\n", rc); + } +#else + handle_fifos(dev); +#endif vendor_specific_irq_clear(dev); } @@ -696,6 +937,7 @@ static int _api_dev_config(const struct device *dev, switch (cfg->data_rate) { case MSPI_DATA_RATE_SINGLE: break; +#if defined(CONFIG_MSPI_DW_DDR) case MSPI_DATA_RATE_DUAL: dev_data->spi_ctrlr0 |= SPI_CTRLR0_INST_DDR_EN_BIT; /* Also need to set DDR_EN bit */ @@ -703,6 +945,7 @@ static int _api_dev_config(const struct device *dev, case MSPI_DATA_RATE_S_D_D: dev_data->spi_ctrlr0 |= SPI_CTRLR0_SPI_DDR_EN_BIT; break; +#endif default: LOG_ERR("Data rate %d not supported", cfg->data_rate); @@ -757,14 +1000,27 @@ static int api_dev_config(const struct device *dev, int rc; if (dev_id != dev_data->dev_id) { +#if defined(CONFIG_MULTITHREADING) rc = k_sem_take(&dev_data->cfg_lock, K_MSEC(CONFIG_MSPI_COMPLETION_TIMEOUT_TOLERANCE)); +#else + if (dev_data->cfg_lock) { + rc = -1; + } else { + dev_data->cfg_lock = true; + rc = 0; + } +#endif if (rc < 0) { LOG_ERR("Failed to switch controller to device"); return -EBUSY; } dev_data->dev_id = dev_id; + +#if defined(CONFIG_MULTITHREADING) + memset(dev_data->cbs, 0, sizeof(dev_data->cbs)); +#endif } if (param_mask == MSPI_DEVICE_CONFIG_NONE && @@ -772,15 +1028,23 @@ static int api_dev_config(const struct device *dev, return 0; } +#if defined(CONFIG_MULTITHREADING) (void)k_sem_take(&dev_data->ctx_lock, K_FOREVER); +#endif rc = _api_dev_config(dev, param_mask, cfg); +#if defined(CONFIG_MULTITHREADING) k_sem_give(&dev_data->ctx_lock); +#endif if (rc < 0) { dev_data->dev_id = NULL; +#if defined(CONFIG_MULTITHREADING) k_sem_give(&dev_data->cfg_lock); +#else + dev_data->cfg_lock = false; +#endif } return rc; @@ -792,12 +1056,17 @@ static int api_get_channel_status(const struct device *dev, uint8_t ch) struct mspi_dw_data *dev_data = dev->data; +#if defined(CONFIG_MULTITHREADING) (void)k_sem_take(&dev_data->ctx_lock, K_FOREVER); +#endif dev_data->dev_id = NULL; +#if defined(CONFIG_MULTITHREADING) k_sem_give(&dev_data->cfg_lock); - k_sem_give(&dev_data->ctx_lock); +#else + dev_data->cfg_lock = false; +#endif return 0; } @@ -813,7 +1082,7 @@ static void tx_control_field(const struct device *dev, } while (shift); } -static int start_next_packet(const struct device *dev, k_timeout_t timeout) +static int start_next_packet(const struct device *dev) { const struct mspi_dw_config *dev_config = dev->config; struct mspi_dw_data *dev_data = dev->data; @@ -824,7 +1093,7 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) (false)); unsigned int key; uint32_t packet_frames; - uint32_t imr; + uint32_t imr = 0; int rc = 0; if (packet->num_bytes == 0 && @@ -872,6 +1141,18 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) return -EINVAL; } +#if defined(CONFIG_MSPI_DMA) + if (dev_data->xfer.xfer_mode == MSPI_DMA) { + /* Check if the packet buffer is accessible */ + if (packet->num_bytes > 0 && + !vendor_specific_dma_accessible_check(dev, packet->data_buf)) { + LOG_ERR("Buffer not DMA accessible: ptr=0x%lx, size=%u", + (uintptr_t)packet->data_buf, packet->num_bytes); + return -EINVAL; + } + } +#endif + if (packet->dir == MSPI_TX || packet->num_bytes == 0) { imr = IMR_TXEIM_BIT; dev_data->ctrlr0 |= FIELD_PREP(CTRLR0_TMOD_MASK, @@ -880,6 +1161,12 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) dev_data->xfer.tx_dummy); write_rxftlr(dev, 0); +#if defined(CONFIG_MSPI_DMA) + } else if (dev_data->xfer.xfer_mode == MSPI_DMA) { + dev_data->ctrlr0 |= FIELD_PREP(CTRLR0_TMOD_MASK, CTRLR0_TMOD_RX); + dev_data->spi_ctrlr0 |= FIELD_PREP(SPI_CTRLR0_WAIT_CYCLES_MASK, + dev_data->xfer.rx_dummy); +#endif } else { uint32_t tmod; uint8_t rx_fifo_threshold; @@ -953,6 +1240,7 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) write_spi_ctrlr0(dev, dev_data->spi_ctrlr0); write_baudr(dev, dev_data->baudr); write_rx_sample_dly(dev, dev_data->rx_sample_dly); +#if defined(CONFIG_MSPI_DW_DDR) if (dev_data->spi_ctrlr0 & (SPI_CTRLR0_SPI_DDR_EN_BIT | SPI_CTRLR0_INST_DDR_EN_BIT)) { int txd = (CONFIG_MSPI_DW_TXD_MUL * dev_data->baudr) / @@ -962,111 +1250,174 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) } else { write_txd_drive_edge(dev, 0); } +#endif if (xip_enabled) { write_ssienr(dev, SSIENR_SSIC_EN_BIT); irq_unlock(key); } - dev_data->buf_pos = packet->data_buf; - dev_data->buf_end = &packet->data_buf[packet->num_bytes]; - - /* Set the TX FIFO threshold and its transmit start level. */ - if (packet->num_bytes) { - /* If there is some data to send/receive, set the threshold to - * the value configured for the driver instance and the start - * level to the maximum possible value (it will be updated later - * in tx_fifo() or tx_dummy_bytes() when TX is to be finished). - * This helps avoid a situation when the TX FIFO becomes empty - * before the transfer is complete and the SSI core finishes the - * transaction and deactivates the CE line. This could occur - * right before the data phase in enhanced SPI modes, when the - * clock stretching feature does not work yet, or in Standard - * SPI mode, where the clock stretching is not available at all. - */ - uint8_t start_level = dev_data->dummy_bytes != 0 - ? dev_config->max_queued_dummy_bytes - 1 - : dev_config->tx_fifo_depth_minus_1; +#if defined(CONFIG_MSPI_DMA) + if (dev_data->xfer.xfer_mode == MSPI_DMA) { + /* For DMA mode, set start level based on transfer length to prevent underflow */ + uint32_t total_transfer_bytes = packet->num_bytes + dev_data->xfer.addr_length + + dev_data->xfer.cmd_length; + uint32_t transfer_frames = total_transfer_bytes >> dev_data->bytes_per_frame_exp; + + /* Use minimum of transfer length or FIFO depth, but at least 1 */ + uint8_t dma_start_level = MIN(transfer_frames - 1, + dev_config->tx_fifo_depth_minus_1); + + dma_start_level = (dma_start_level > 0 ? dma_start_level : 1); + + /* Only TXFTHR needs to be set to the minimum number of frames */ + write_txftlr(dev, FIELD_PREP(TXFTLR_TXFTHR_MASK, dma_start_level)); + write_dmatdlr(dev, FIELD_PREP(DMATDLR_DMATDL_MASK, dev_config->dma_tx_data_level)); + write_dmardlr(dev, FIELD_PREP(DMARDLR_DMARDL_MASK, dev_config->dma_rx_data_level)); + write_dmacr(dev, DMACR_TDMAE_BIT | DMACR_RDMAE_BIT); + write_imr(dev, 0); + write_ssienr(dev, SSIENR_SSIC_EN_BIT); - write_txftlr(dev, FIELD_PREP(TXFTLR_TXFTHR_MASK, start_level) | - FIELD_PREP(TXFTLR_TFT_MASK, - dev_config->tx_fifo_threshold)); + vendor_specific_start_dma_xfer(dev); } else { - uint32_t total_tx_entries = 0; +#endif + /* PIO mode */ + dev_data->buf_pos = packet->data_buf; + dev_data->buf_end = &packet->data_buf[packet->num_bytes]; + /* Set the TX FIFO threshold and its transmit start level. */ + if (packet->num_bytes) { + /* If there is some data to send/receive, set the threshold to + * the value configured for the driver instance and the start + * level to the maximum possible value (it will be updated later + * in tx_fifo() or tx_dummy_bytes() when TX is to be finished). + * This helps avoid a situation when the TX FIFO becomes empty + * before the transfer is complete and the SSI core finishes the + * transaction and deactivates the CE line. This could occur + * right before the data phase in enhanced SPI modes, when the + * clock stretching feature does not work yet, or in Standard + * SPI mode, where the clock stretching is not available at all. + */ + uint8_t start_level = dev_data->dummy_bytes != 0 + ? dev_config->max_queued_dummy_bytes - 1 + : dev_config->tx_fifo_depth_minus_1; - /* It the whole transfer is to contain only the command and/or - * address, set up the transfer to start right after entries - * for those appear in the TX FIFO, and the threshold to 0, - * so that the interrupt occurs when the TX FIFO gets emptied. - */ - if (dev_data->xfer.cmd_length) { - if (dev_data->standard_spi) { - total_tx_entries += dev_data->xfer.cmd_length; - } else { - total_tx_entries += 1; + write_txftlr(dev, FIELD_PREP(TXFTLR_TXFTHR_MASK, start_level) | + FIELD_PREP(TXFTLR_TFT_MASK, + dev_config->tx_fifo_threshold)); + + } else { + uint32_t total_tx_entries = 0; + + /* It the whole transfer is to contain only the command and/or + * address, set up the transfer to start right after entries + * for those appear in the TX FIFO, and the threshold to 0, + * so that the interrupt occurs when the TX FIFO gets emptied. + */ + if (dev_data->xfer.cmd_length) { + if (dev_data->standard_spi) { + total_tx_entries += dev_data->xfer.cmd_length; + } else { + total_tx_entries += 1; + } } - } - if (dev_data->xfer.addr_length) { - if (dev_data->standard_spi) { - total_tx_entries += dev_data->xfer.addr_length; - } else { - total_tx_entries += 1; + if (dev_data->xfer.addr_length) { + if (dev_data->standard_spi) { + total_tx_entries += dev_data->xfer.addr_length; + } else { + total_tx_entries += 1; + } } + + write_txftlr(dev, FIELD_PREP(TXFTLR_TXFTHR_MASK, + total_tx_entries - 1)); } - write_txftlr(dev, FIELD_PREP(TXFTLR_TXFTHR_MASK, - total_tx_entries - 1)); - } + /* Ensure that there will be no interrupt from the controller yet. */ + write_imr(dev, 0); + /* Enable the controller. This must be done before DR is written. */ + write_ssienr(dev, SSIENR_SSIC_EN_BIT); - /* Ensure that there will be no interrupt from the controller yet. */ - write_imr(dev, 0); - /* Enable the controller. This must be done before DR is written. */ - write_ssienr(dev, SSIENR_SSIC_EN_BIT); + /* Since the FIFO depth in SSI is always at least 8, it can be safely + * assumed that the command and address fields (max. 2 and 4 bytes, + * respectively) can be written here before the TX FIFO gets filled up. + */ + if (dev_data->standard_spi) { + if (dev_data->xfer.cmd_length) { + tx_control_field(dev, packet->cmd, + dev_data->xfer.cmd_length); + } - /* Since the FIFO depth in SSI is always at least 8, it can be safely - * assumed that the command and address fields (max. 2 and 4 bytes, - * respectively) can be written here before the TX FIFO gets filled up. - */ - if (dev_data->standard_spi) { - if (dev_data->xfer.cmd_length) { - tx_control_field(dev, packet->cmd, - dev_data->xfer.cmd_length); - } + if (dev_data->xfer.addr_length) { + tx_control_field(dev, packet->address, + dev_data->xfer.addr_length); + } + } else { + if (dev_data->xfer.cmd_length) { + write_dr(dev, packet->cmd); + } - if (dev_data->xfer.addr_length) { - tx_control_field(dev, packet->address, - dev_data->xfer.addr_length); - } - } else { - if (dev_data->xfer.cmd_length) { - write_dr(dev, packet->cmd); + if (dev_data->xfer.addr_length) { + write_dr(dev, packet->address); + } } - if (dev_data->xfer.addr_length) { - write_dr(dev, packet->address); + /* Prefill TX FIFO with any data we can */ + if (dev_data->dummy_bytes && tx_dummy_bytes(dev, NULL)) { + imr = IMR_RXFIM_BIT; + } else if (packet->dir == MSPI_TX && packet->num_bytes) { + tx_data(dev, packet); } - } - /* Prefill TX FIFO with any data we can */ - if (dev_data->dummy_bytes && tx_dummy_bytes(dev)) { - imr = IMR_RXFIM_BIT; - } else if (packet->dir == MSPI_TX && packet->num_bytes) { - tx_data(dev, packet); + /* Enable interrupts now and wait until the packet is done unless async. */ + write_imr(dev, imr); +#if defined(CONFIG_MSPI_DMA) } +#endif - /* Enable interrupts now and wait until the packet is done. */ - write_imr(dev, imr); /* Write SER to start transfer */ write_ser(dev, BIT(dev_data->dev_id->dev_idx)); +#if defined(CONFIG_MULTITHREADING) + k_timeout_t timeout = K_MSEC(dev_data->xfer.timeout); + + /* For async transfer, start the timeout timer and exit. */ + if (dev_data->xfer.async) { + k_timer_start(&dev_data->async_timer, timeout, K_NO_WAIT); + + return 0; + } + + /* For sync transfer, wait until the packet is finished. */ rc = k_sem_take(&dev_data->finished, timeout); + if (rc < 0) { + rc = -ETIMEDOUT; + } +#else + if (!WAIT_FOR(dev_data->finished, + dev_data->xfer.timeout * USEC_PER_MSEC, + NULL)) { + rc = -ETIMEDOUT; + } + + dev_data->finished = false; +#endif + + return finalize_packet(dev, rc); +} + +static int finalize_packet(const struct device *dev, int rc) +{ + struct mspi_dw_data *dev_data = dev->data; + bool xip_enabled = COND_CODE_1(CONFIG_MSPI_XIP, + (dev_data->xip_enabled != 0), + (false)); + if (read_risr(dev) & RISR_RXOIR_BIT) { LOG_ERR("RX FIFO overflow occurred"); rc = -EIO; - } else if (rc < 0) { + } else if (rc == -ETIMEDOUT) { LOG_ERR("Transfer timed out"); - rc = -ETIMEDOUT; } /* Disable the controller. This will immediately halt the transfer @@ -1075,10 +1426,10 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) if (xip_enabled) { /* If XIP is enabled, the controller must be kept enabled, * so disable it only momentarily if there's a need to halt - * a transfer that has timeout out. + * a transfer that ended up with an error. */ - if (rc == -ETIMEDOUT) { - key = irq_lock(); + if (rc < 0) { + unsigned int key = irq_lock(); write_ssienr(dev, 0); write_ssienr(dev, SSIENR_SSIC_EN_BIT); @@ -1088,13 +1439,14 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) } else { write_ssienr(dev, 0); } + /* Clear SER */ write_ser(dev, 0); if (dev_data->dev_id->ce.port) { int rc2; - /* Do not use `rc` to not overwrite potential timeout error. */ + /* Do not use `rc` to not overwrite potential packet error. */ rc2 = gpio_pin_set_dt(&dev_data->dev_id->ce, 0); if (rc2 < 0) { LOG_ERR("Failed to deactivate CE line (%d)", rc2); @@ -1137,10 +1489,18 @@ static int _api_transceive(const struct device *dev, dev_data->xfer = *req; + /* For async, only the first packet is started here, next ones, if any, + * are started by ISR. + */ + if (req->async) { + dev_data->packets_done = 0; + return start_next_packet(dev); + } + for (dev_data->packets_done = 0; dev_data->packets_done < dev_data->xfer.num_packet; dev_data->packets_done++) { - rc = start_next_packet(dev, K_MSEC(dev_data->xfer.timeout)); + rc = start_next_packet(dev); if (rc < 0) { return rc; } @@ -1154,16 +1514,15 @@ static int api_transceive(const struct device *dev, const struct mspi_xfer *req) { struct mspi_dw_data *dev_data = dev->data; - int rc, rc2; + int rc; if (dev_id != dev_data->dev_id) { LOG_ERR("Controller is not configured for this device"); return -EINVAL; } - /* TODO: add support for asynchronous transfers */ - if (req->async) { - LOG_ERR("Asynchronous transfers are not supported"); + if (req->async && !IS_ENABLED(CONFIG_MULTITHREADING)) { + LOG_ERR("Asynchronous transfers require multithreading"); return -ENOTSUP; } @@ -1173,7 +1532,9 @@ static int api_transceive(const struct device *dev, return rc; } +#if defined(CONFIG_MULTITHREADING) (void)k_sem_take(&dev_data->ctx_lock, K_FOREVER); +#endif if (dev_data->suspended) { rc = -EFAULT; @@ -1181,7 +1542,22 @@ static int api_transceive(const struct device *dev, rc = _api_transceive(dev, req); } + if (req->async && rc >= 0) { + return rc; + } + + return finalize_transceive(dev, rc); +} + +static int finalize_transceive(const struct device *dev, int rc) +{ + int rc2; + +#if defined(CONFIG_MULTITHREADING) + struct mspi_dw_data *dev_data = dev->data; + k_sem_give(&dev_data->ctx_lock); +#endif rc2 = pm_device_runtime_put(dev); if (rc2 < 0) { @@ -1192,6 +1568,33 @@ static int api_transceive(const struct device *dev, return rc; } +#if defined(CONFIG_MULTITHREADING) +static int api_register_callback(const struct device *dev, + const struct mspi_dev_id *dev_id, + const enum mspi_bus_event evt_type, + mspi_callback_handler_t cb, + struct mspi_callback_context *ctx) +{ + struct mspi_dw_data *dev_data = dev->data; + + if (dev_id != dev_data->dev_id) { + LOG_ERR("Controller is not configured for this device"); + return -EINVAL; + } + + if (evt_type != MSPI_BUS_ERROR && + evt_type != MSPI_BUS_XFER_COMPLETE && + evt_type != MSPI_BUS_TIMEOUT) { + LOG_ERR("Callback type %d not supported", evt_type); + return -ENOTSUP; + } + + dev_data->cbs[evt_type] = cb; + dev_data->cb_ctxs[evt_type] = ctx; + return 0; +} +#endif /* defined(CONFIG_MULTITHREADING) */ + #if defined(CONFIG_MSPI_TIMING) static int api_timing_config(const struct device *dev, const struct mspi_dev_id *dev_id, @@ -1332,7 +1735,9 @@ static int api_xip_config(const struct device *dev, return rc; } +#if defined(CONFIG_MULTITHREADING) (void)k_sem_take(&dev_data->ctx_lock, K_FOREVER); +#endif if (dev_data->suspended) { rc = -EFAULT; @@ -1340,7 +1745,9 @@ static int api_xip_config(const struct device *dev, rc = _api_xip_config(dev, dev_id, cfg); } +#if defined(CONFIG_MULTITHREADING) k_sem_give(&dev_data->ctx_lock); +#endif rc2 = pm_device_runtime_put(dev); if (rc2 < 0) { @@ -1391,8 +1798,12 @@ static int dev_pm_action_cb(const struct device *dev, return rc; } #endif +#if defined(CONFIG_MULTITHREADING) if (xip_enabled || k_sem_take(&dev_data->ctx_lock, K_NO_WAIT) != 0) { +#else + if (xip_enabled) { +#endif LOG_ERR("Controller in use, cannot be suspended"); return -EBUSY; } @@ -1401,7 +1812,9 @@ static int dev_pm_action_cb(const struct device *dev, vendor_specific_suspend(dev); +#if defined(CONFIG_MULTITHREADING) k_sem_give(&dev_data->ctx_lock); +#endif return 0; } @@ -1420,12 +1833,26 @@ static int dev_init(const struct device *dev) vendor_specific_init(dev); + dev_data->ctrlr0 |= FIELD_PREP(CTRLR0_SSI_IS_MST_BIT, + dev_config->op_mode == MSPI_OP_MODE_CONTROLLER); + dev_config->irq_config(); +#if defined(CONFIG_MULTITHREADING) + dev_data->dev = dev; k_sem_init(&dev_data->finished, 0, 1); k_sem_init(&dev_data->cfg_lock, 1, 1); k_sem_init(&dev_data->ctx_lock, 1, 1); + k_timer_init(&dev_data->async_timer, async_timeout_timer_handler, NULL); + k_work_init(&dev_data->async_timeout_work, async_timeout_work_handler); + k_work_init(&dev_data->async_packet_work, async_packet_work_handler); +#endif + +#if defined(CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE) + k_work_init(&dev_data->fifo_work, fifo_work_handler); +#endif + for (ce_gpio = dev_config->ce_gpios; ce_gpio < &dev_config->ce_gpios[dev_config->ce_gpios_len]; ce_gpio++) { @@ -1441,9 +1868,6 @@ static int dev_init(const struct device *dev) } } - /* Make sure controller is disabled. */ - write_ssienr(dev, 0); - #if defined(CONFIG_PINCTRL) if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { rc = pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_SLEEP); @@ -1454,7 +1878,15 @@ static int dev_init(const struct device *dev) } #endif - return pm_device_driver_init(dev, dev_pm_action_cb); + rc = pm_device_driver_init(dev, dev_pm_action_cb); + if (rc < 0) { + return rc; + } + + /* Make sure controller is disabled. */ + write_ssienr(dev, 0); + + return 0; } static DEVICE_API(mspi, drv_api) = { @@ -1462,6 +1894,9 @@ static DEVICE_API(mspi, drv_api) = { .dev_config = api_dev_config, .get_channel_status = api_get_channel_status, .transceive = api_transceive, +#if defined(CONFIG_MULTITHREADING) + .register_callback = api_register_callback, +#endif #if defined(CONFIG_MSPI_TIMING) .timing_config = api_timing_config, #endif @@ -1512,9 +1947,16 @@ static DEVICE_API(mspi, drv_api) = { DT_INST_PROP_OR(inst, rx_fifo_threshold, \ 1 * RX_FIFO_DEPTH(inst) / 8 - 1) +#define MSPI_DW_DMA_DATA_LEVELS(inst) \ + .dma_tx_data_level = \ + DT_INST_PROP_OR(inst, dma_transmit_data_level, 0), \ + .dma_rx_data_level = \ + DT_INST_PROP_OR(inst, dma_receive_data_level, 0) + #define MSPI_DW_INST(inst) \ PM_DEVICE_DT_INST_DEFINE(inst, dev_pm_action_cb); \ IF_ENABLED(CONFIG_PINCTRL, (PINCTRL_DT_INST_DEFINE(inst);)) \ + VENDOR_SPECIFIC_DATA_DEFINE(inst); \ static void irq_config##inst(void) \ { \ LISTIFY(DT_INST_NUM_IRQS(inst), \ @@ -1523,6 +1965,7 @@ static DEVICE_API(mspi, drv_api) = { static struct mspi_dw_data dev##inst##_data; \ static const struct mspi_dw_config dev##inst##_config = { \ MSPI_DW_MMIO_ROM_INIT(DT_DRV_INST(inst)), \ + .wrapper_regs = (void *)DT_INST_REG_ADDR(inst), \ .irq_config = irq_config##inst, \ .clock_frequency = MSPI_DW_CLOCK_FREQUENCY(inst), \ IF_ENABLED(CONFIG_PINCTRL, \ @@ -1530,9 +1973,12 @@ static DEVICE_API(mspi, drv_api) = { IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, ce_gpios), \ (MSPI_DW_CE_GPIOS(inst),)) \ MSPI_DW_FIFO_PROPS(inst), \ + IF_ENABLED(CONFIG_MSPI_DMA, (MSPI_DW_DMA_DATA_LEVELS(inst),)) \ + .vendor_specific_data = VENDOR_SPECIFIC_DATA_GET(inst), \ DEFINE_REG_ACCESS(inst) \ .sw_multi_periph = \ DT_INST_PROP(inst, software_multiperipheral), \ + .op_mode = DT_INST_STRING_TOKEN(inst, op_mode), \ }; \ DEVICE_DT_INST_DEFINE(inst, \ dev_init, PM_DEVICE_DT_INST_GET(inst), \ diff --git a/drivers/mspi/mspi_dw.h b/drivers/mspi/mspi_dw.h index 28e4bed016e7..0d015ae3db03 100644 --- a/drivers/mspi/mspi_dw.h +++ b/drivers/mspi/mspi_dw.h @@ -19,6 +19,7 @@ */ /* CTRLR0 - Control Register 0 */ +#define CTRLR0_SSI_IS_MST_BIT BIT(31) #define CTRLR0_SPI_FRF_MASK COND_CODE_1(SSI_VERSION_2, GENMASK(22, 21), GENMASK(23, 22)) #define CTRLR0_SPI_FRF_STANDARD 0UL #define CTRLR0_SPI_FRF_DUAL 1UL @@ -172,6 +173,22 @@ #define XIP_WRITE_CTRL_FRF_QUAD 2UL #define XIP_WRITE_CTRL_FRF_OCTAL 3UL +/* DMACR - DMA Control Register */ +#define DMACR_ATW_MASK GENMASK(4, 3) +#define DMACR_ATW_1 0UL +#define DMACR_ATW_2 1UL +#define DMACR_ATW_4 2UL +#define DMACR_ATW_8 3UL +#define DMACR_IDMAE_BIT BIT(2) +#define DMACR_TDMAE_BIT BIT(1) +#define DMACR_RDMAE_BIT BIT(0) + +/* DMATDLR - DMA Transmit Data Level */ +#define DMATDLR_DMATDL_MASK GENMASK(3, 0) + +/* DMARDLR - DMA Receive Data Level */ +#define DMARDLR_DMARDL_MASK GENMASK(3, 0) + /* Register access helpers. */ #define USES_AUX_REG(inst) + DT_INST_PROP(inst, aux_reg_enable) #define AUX_REG_INSTANCES (0 DT_INST_FOREACH_STATUS_OKAY(USES_AUX_REG)) diff --git a/drivers/mspi/mspi_dw_vendor_specific.h b/drivers/mspi/mspi_dw_vendor_specific.h index d32a53ac2939..0b1fcf1ca7e0 100644 --- a/drivers/mspi/mspi_dw_vendor_specific.h +++ b/drivers/mspi/mspi_dw_vendor_specific.h @@ -97,7 +97,221 @@ static inline int vendor_specific_xip_disable(const struct device *dev, } #endif /* defined(CONFIG_MSPI_XIP) */ -#else +#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_qspi_v2) +#include + +static inline void vendor_specific_init(const struct device *dev) +{ + const struct mspi_dw_config *config = dev->config; + NRF_QSPI_Type *preg = (NRF_QSPI_Type *)config->wrapper_regs; + + preg->EVENTS_CORE = 0; + preg->EVENTS_DMA.DONE = 0; + + preg->INTENSET = BIT(QSPI_INTENSET_CORE_Pos) + | BIT(QSPI_INTENSET_DMADONE_Pos); +} + +static inline void vendor_specific_suspend(const struct device *dev) +{ + const struct mspi_dw_config *config = dev->config; + NRF_QSPI_Type *preg = (NRF_QSPI_Type *)config->wrapper_regs; + + preg->ENABLE = 0; +} + +static inline void vendor_specific_resume(const struct device *dev) +{ + const struct mspi_dw_config *config = dev->config; + NRF_QSPI_Type *preg = (NRF_QSPI_Type *)config->wrapper_regs; + + preg->ENABLE = 1; + +} + +static inline void vendor_specific_irq_clear(const struct device *dev) +{ + const struct mspi_dw_config *config = dev->config; + NRF_QSPI_Type *preg = (NRF_QSPI_Type *)config->wrapper_regs; + + preg->EVENTS_CORE = 0; + preg->EVENTS_DMA.DONE = 0; +} + +/* DMA support */ + +#define EVDMA_ATTR_LEN_Pos (0UL) +#define EVDMA_ATTR_LEN_Msk (0x00FFFFFFUL) + +#define EVDMA_ATTR_ATTR_Pos (24UL) +#define EVDMA_ATTR_ATTR_Msk (0x3FUL << EVDMA_ATTR_ATTR_Pos) + +#define EVDMA_ATTR_32AXI_Pos (30UL) +#define EVDMA_ATTR_32AXI_Msk (0x1UL << EVDMA_ATTR_32AXI_Pos) + +#define EVDMA_ATTR_EVENTS_Pos (31UL) +#define EVDMA_ATTR_EVENTS_Msk (0x1UL << EVDMA_ATTR_EVENTS_Pos) + +typedef enum { + EVDMA_BYTE_SWAP = 0, + EVDMA_JOBLIST = 1, + EVDMA_BUFFER_FILL = 2, + EVDMA_FIXED_ATTR = 3, + EVDMA_STATIC_ADDR = 4, + EVDMA_PLAIN_DATA_BUF_WR = 5, +} EVDMA_ATTR_Type; + +/* Setup EVDMA attribute with the following configuratrion */ +#define EVDMA_ATTRIBUTE (BIT(EVDMA_BYTE_SWAP) | BIT(EVDMA_JOBLIST) | \ + BIT(EVDMA_BUFFER_FILL) | BIT(EVDMA_FIXED_ATTR) | \ + BIT(EVDMA_STATIC_ADDR) | BIT(EVDMA_PLAIN_DATA_BUF_WR)) + +typedef struct { + uint8_t *addr; + uint32_t attr; +} EVDMA_JOB_Type; + +#define EVDMA_JOB(BUFFER, SIZE, ATTR) \ + (EVDMA_JOB_Type) { .addr = (uint8_t *)BUFFER, .attr = (ATTR << EVDMA_ATTR_ATTR_Pos | SIZE) } +#define EVDMA_NULL_JOB() \ + (EVDMA_JOB_Type) { .addr = (uint8_t *)0, .attr = 0 } +typedef struct { + EVDMA_JOB_Type *tx_job; + EVDMA_JOB_Type *rx_job; +} QSPI_TRANSFER_LIST_Type; + +/* Number of jobs needed for transmit trasaction */ +#define MAX_NUM_JOBS 5 + +/* Vendor-specific data structure for Nordic QSPI */ +typedef struct { + QSPI_TRANSFER_LIST_Type *transfer_list; + EVDMA_JOB_Type *joblist; +} nordic_qspi_vendor_data_t; + +/* Static allocation macros for vendor-specific data */ +#define VENDOR_SPECIFIC_DATA_DEFINE(inst) \ + static QSPI_TRANSFER_LIST_Type mspi_dw_##inst##_transfer_list; \ + static EVDMA_JOB_Type mspi_dw_##inst##_joblist[MAX_NUM_JOBS]; \ + static const nordic_qspi_vendor_data_t mspi_dw_##inst##_vendor_data = { \ + .transfer_list = &mspi_dw_##inst##_transfer_list, \ + .joblist = &mspi_dw_##inst##_joblist[0] \ + }; + +#define VENDOR_SPECIFIC_DATA_GET(inst) (void *)&mspi_dw_##inst##_vendor_data + +/* Temporarily hard-coded as not in MDK yet */ +#define QSPI_TMOD_OFFSET (0x490UL) +#define QSPI_TMOD_TX_AND_RX (0x0) +#define QSPI_TMOD_TX_ONLY (0x1) +#define QSPI_TMOD_RX_ONLY (0x2) +static inline void vendor_specific_start_dma_xfer(const struct device *dev) +{ + struct mspi_dw_data *dev_data = dev->data; + const struct mspi_dw_config *config = dev->config; + const struct mspi_xfer_packet *packet = + &dev_data->xfer.packets[dev_data->packets_done]; + NRF_QSPI_Type *preg = (NRF_QSPI_Type *)config->wrapper_regs; + + /* Use vendor-specific data from config - stores job and transfer lists */ + const nordic_qspi_vendor_data_t *vendor_data = (const nordic_qspi_vendor_data_t *) + config->vendor_specific_data; + + QSPI_TRANSFER_LIST_Type *transfer_list = vendor_data->transfer_list; + EVDMA_JOB_Type *joblist = vendor_data->joblist; + + int tmod = 0; + int job_idx = 0; + + /* Set up tx job pointer to the first job */ + transfer_list->tx_job = &joblist[0]; + + /* + * The Command and Address will always have a length of 4 from the DMA's + * perspective. QSPI peripheral will use length of data specified in core registers + */ + if (dev_data->xfer.cmd_length > 0) { + joblist[job_idx++] = EVDMA_JOB(&packet->cmd, 4, EVDMA_ATTRIBUTE); + } + if (dev_data->xfer.addr_length > 0) { + joblist[job_idx++] = EVDMA_JOB(&packet->address, 4, EVDMA_ATTRIBUTE); + } + + if (packet->dir == MSPI_TX) { + preg->CONFIG.RXTRANSFERLENGTH = 0; + + if (packet->num_bytes > 0) { + joblist[job_idx++] = EVDMA_JOB(packet->data_buf, packet->num_bytes, + EVDMA_ATTRIBUTE); + } + + /* Always terminate with null job */ + joblist[job_idx] = EVDMA_NULL_JOB(); + /* rx_job is always EVDMA_NULL_JOB() for transmit */ + transfer_list->rx_job = &joblist[job_idx]; + tmod = QSPI_TMOD_TX_ONLY; + } else { + preg->CONFIG.RXTRANSFERLENGTH = ((packet->num_bytes + dev_data->xfer.addr_length + + dev_data->xfer.cmd_length) >> + dev_data->bytes_per_frame_exp) - 1; + + /* If sending address or command while being configured as controller */ + if (job_idx > 0 && config->op_mode == MSPI_OP_MODE_CONTROLLER) { + tmod = QSPI_TMOD_TX_AND_RX; + + /* After command and address, setup RX job for data */ + joblist[job_idx++] = EVDMA_NULL_JOB(); + transfer_list->rx_job = &joblist[job_idx]; + joblist[job_idx++] = EVDMA_JOB(packet->data_buf, packet->num_bytes, + EVDMA_ATTRIBUTE); + joblist[job_idx] = EVDMA_NULL_JOB(); + } else { + /* Sending command or address while configured as target isn't supported */ + tmod = QSPI_TMOD_RX_ONLY; + + transfer_list->rx_job = &joblist[0]; + joblist[0] = EVDMA_JOB(packet->data_buf, packet->num_bytes, + EVDMA_ATTRIBUTE); + joblist[1] = EVDMA_NULL_JOB(); + transfer_list->tx_job = &joblist[1]; + } + } + + /* + * In slave mode, a tmod register in the wrapper also needs to be set. Currently + * the address not in MDK so this is a temporary fix. + */ + uintptr_t tmod_addr = (uintptr_t)preg + QSPI_TMOD_OFFSET; + + sys_write32(tmod, tmod_addr); + + preg->CONFIG.TXBURSTLENGTH = config->tx_fifo_depth_minus_1 + 1 + - config->dma_tx_data_level; + preg->CONFIG.RXBURSTLENGTH = config->dma_rx_data_level + 1; + preg->DMA.CONFIG.LISTPTR = (uint32_t)transfer_list; + + preg->TASKS_START = 1; +} + +static inline bool vendor_specific_dma_accessible_check(const struct device *dev, + const uint8_t *data_buf) +{ + const struct mspi_dw_config *config = dev->config; + NRF_QSPI_Type *preg = (NRF_QSPI_Type *)config->wrapper_regs; + + return nrf_dma_accessible_check(preg, data_buf); +} + +static inline bool vendor_specific_read_dma_irq(const struct device *dev) +{ + const struct mspi_dw_config *config = dev->config; + NRF_QSPI_Type *preg = (NRF_QSPI_Type *)config->wrapper_regs; + + return (bool) preg->EVENTS_DMA.DONE; +} + +#else /* Supply empty vendor specific macros for generic case */ + static inline void vendor_specific_init(const struct device *dev) { ARG_UNUSED(dev); @@ -134,4 +348,33 @@ static inline int vendor_specific_xip_disable(const struct device *dev, return 0; } -#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_exmif) */ +#if defined(CONFIG_MSPI_DMA) +static inline void vendor_specific_start_dma_xfer(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static inline bool vendor_specific_dma_accessible_check(const struct device *dev, + const uint8_t *data_buf) { + ARG_UNUSED(dev); + ARG_UNUSED(data_buf); + + return true; +} +static inline bool vendor_specific_read_dma_irq(const struct device *dev) +{ + ARG_UNUSED(dev); + + return true; +} +#endif /* defined(CONFIG_MSPI_DMA) */ +#endif /* Empty vendor specific macros */ + +/* Empty macros for generic case - no vendor-specific data */ +#ifndef VENDOR_SPECIFIC_DATA_DEFINE +#define VENDOR_SPECIFIC_DATA_DEFINE(inst) +#endif + +#ifndef VENDOR_SPECIFIC_DATA_GET +#define VENDOR_SPECIFIC_DATA_GET(inst) (void *)NULL +#endif diff --git a/drivers/pinctrl/pinctrl_nrf.c b/drivers/pinctrl/pinctrl_nrf.c index bbcaea06435f..3ad358158a80 100644 --- a/drivers/pinctrl/pinctrl_nrf.c +++ b/drivers/pinctrl/pinctrl_nrf.c @@ -5,7 +5,6 @@ */ #include -#include #include #include @@ -15,7 +14,7 @@ BUILD_ASSERT(((NRF_PULL_NONE == NRF_GPIO_PIN_NOPULL) && (NRF_PULL_UP == NRF_GPIO_PIN_PULLUP)), "nRF pinctrl pull settings do not match HAL values"); -#if defined(GPIO_PIN_CNF_DRIVE_E0E1) || defined(GPIO_PIN_CNF_DRIVE0_E0) +#if NRF_GPIO_HAS_DRIVE_EXTRA #define NRF_DRIVE_COUNT (NRF_DRIVE_E0E1 + 1) #else #define NRF_DRIVE_COUNT (NRF_DRIVE_H0D1 + 1) @@ -29,7 +28,7 @@ static const nrf_gpio_pin_drive_t drive_modes[NRF_DRIVE_COUNT] = { [NRF_DRIVE_D0H1] = NRF_GPIO_PIN_D0H1, [NRF_DRIVE_S0D1] = NRF_GPIO_PIN_S0D1, [NRF_DRIVE_H0D1] = NRF_GPIO_PIN_H0D1, -#if defined(GPIO_PIN_CNF_DRIVE_E0E1) || defined(GPIO_PIN_CNF_DRIVE0_E0) +#if NRF_GPIO_HAS_DRIVE_EXTRA [NRF_DRIVE_E0E1] = NRF_GPIO_PIN_E0E1, #endif }; @@ -46,11 +45,11 @@ static const nrf_gpio_pin_drive_t drive_modes[NRF_DRIVE_COUNT] = { #define NRF_PSEL_UART(reg, line) ((NRF_UARTE_Type *)reg)->PSEL.line #endif -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_spi) || defined(CONFIG_NRFX_SPI) -#define NRF_PSEL_SPIM(reg, line) ((NRF_SPI_Type *)reg)->PSEL##line -#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_spim) || defined(CONFIG_NRFX_SPIM) +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_spim) || defined(CONFIG_NRFX_SPIM) #include #define NRF_PSEL_SPIM(reg, line) ((NRF_SPIM_Type *)reg)->PSEL.line +#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_spi) || defined(CONFIG_NRFX_SPI) +#define NRF_PSEL_SPIM(reg, line) ((NRF_SPI_Type *)reg)->PSEL##line #endif #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_spis) || defined(CONFIG_NRFX_SPIS) @@ -111,75 +110,23 @@ static const nrf_gpio_pin_drive_t drive_modes[NRF_DRIVE_COUNT] = { #define NRF_PSEL_TDM(reg, line) ((NRF_TDM_Type *)reg)->PSEL.line #endif -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_gpio_pad_group) -#define GPIO_HAS_PAD_GROUP 1 -#else -#define GPIO_HAS_PAD_GROUP 0 -#endif - -#if GPIO_HAS_PAD_GROUP - -#define GPIO_PAD_GROUP_GET_OR_NULL(idx, _) \ - DEVICE_DT_GET_OR_NULL(DT_NODELABEL(_CONCAT(gpio_pad_group, idx))) - -static const struct device *const pad_groups[] = { - LISTIFY(10, GPIO_PAD_GROUP_GET_OR_NULL, (,)) -}; - -static atomic_t pad_group_masks[ARRAY_SIZE(pad_groups)]; - -static int pad_group_request_pin(uint16_t pin_number) -{ - uint8_t port_number = NRF_GET_PORT(pin_number); - uint8_t port_pin_number = NRF_GET_PORT_PIN(pin_number); - const struct device *pad_group = pad_groups[port_number]; - atomic_t *pad_group_mask = &pad_group_masks[port_number]; - - if (atomic_test_and_set_bit(pad_group_mask, port_pin_number)) { - /* already requested */ - return 0; - } - - if (pm_device_runtime_get(pad_group)) { - atomic_clear_bit(pad_group_mask, port_pin_number); - return -EIO; - } - - return 0; -} +#if NRF_GPIO_HAS_RETENTION_SETCLEAR -static int pad_group_release_pin(uint16_t pin_number) +static void port_pin_retain_set(uint16_t pin_number, bool enable) { - uint8_t port_number = NRF_GET_PORT(pin_number); - uint8_t port_pin_number = NRF_GET_PORT_PIN(pin_number); - const struct device *pad_group = pad_groups[port_number]; - atomic_t *pad_group_mask = &pad_group_masks[port_number]; - - if (!atomic_test_and_clear_bit(pad_group_mask, port_pin_number)) { - /* already released */ - return 0; + if (enable) { + nrf_gpio_pin_retain_enable(pin_number); + } else { + nrf_gpio_pin_retain_disable(pin_number); } - - if (pm_device_runtime_put(pad_group)) { - atomic_set_bit(pad_group_mask, port_pin_number); - return -EIO; - } - - return 0; } #else -static int pad_group_request_pin(uint16_t pin_number) -{ - ARG_UNUSED(pin_number); - return 0; -} - -static int pad_group_release_pin(uint16_t pin_number) +static void port_pin_retain_set(uint16_t pin_number, bool enable) { ARG_UNUSED(pin_number); - return 0; + ARG_UNUSED(enable); } #endif @@ -201,6 +148,18 @@ static void port_pin_clock_set(uint16_t pin_number, bool enable) #endif +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_hpf_mspi_controller) || \ + defined(CONFIG_MSPI_HPF) || \ + DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(nordic_nrf_vpr_coprocessor, pinctrl_0) +#if defined(CONFIG_SOC_SERIES_NRF54LX) +#define NRF_PSEL_SDP_MSPI(psel) \ + nrf_gpio_pin_control_select(psel, NRF_GPIO_PIN_SEL_VPR); +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +/* On nRF54H, pin routing is controlled by secure domain, via UICR. */ +#define NRF_PSEL_SDP_MSPI(psel) +#endif +#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_hpf_mspi_controller) || ... */ + int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) { @@ -265,6 +224,14 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, dir = NRF_GPIO_PIN_DIR_INPUT; input = NRF_GPIO_PIN_INPUT_CONNECT; break; +#if defined(NRF_SPIM_HAS_HW_CSN) && NRF_SPIM_HAS_HW_CSN + case NRF_FUN_SPIM_CSN: + NRF_PSEL_SPIM(reg, CSN) = psel; + write = 1U; + dir = NRF_GPIO_PIN_DIR_OUTPUT; + input = NRF_GPIO_PIN_INPUT_DISCONNECT; + break; +#endif #endif /* defined(NRF_PSEL_SPIM) */ #if defined(NRF_PSEL_SPIS) case NRF_FUN_SPIS_SCK: @@ -486,7 +453,7 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, #endif /* defined(NRF_PSEL_TDM) */ #if defined(NRF_GRTC_CLKOUT_FAST) case NRF_FUN_GRTC_CLKOUT_FAST: -#if NRF_GPIO_HAS_SEL && defined(GPIO_PIN_CNF_CTRLSEL_GRTC) +#if NRF_GPIO_HAS_SEL && NRF_GPIO_HAS_CTRLSEL_GRTC nrf_gpio_pin_control_select(psel, NRF_GPIO_PIN_SEL_GRTC); #endif dir = NRF_GPIO_PIN_DIR_OUTPUT; @@ -495,7 +462,7 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, #endif /* defined(NRF_GRTC_CLKOUT_FAST) */ #if defined(NRF_GRTC_CLKOUT_SLOW) case NRF_FUN_GRTC_CLKOUT_32K: -#if NRF_GPIO_HAS_SEL && defined(GPIO_PIN_CNF_CTRLSEL_GRTC) +#if NRF_GPIO_HAS_SEL && NRF_GPIO_HAS_CTRLSEL_GRTC nrf_gpio_pin_control_select(psel, NRF_GPIO_PIN_SEL_GRTC); #endif dir = NRF_GPIO_PIN_DIR_OUTPUT; @@ -513,7 +480,8 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, input = NRF_GPIO_PIN_INPUT_CONNECT; break; #endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_can) */ -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_exmif) +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_exmif) || \ + DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_exmif_spi) /* Pin routing is controlled by secure domain, via UICR */ case NRF_FUN_EXMIF_CK: case NRF_FUN_EXMIF_DQ0: @@ -531,6 +499,19 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, input = NRF_GPIO_PIN_INPUT_DISCONNECT; break; #endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_exmif) */ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_qspi_v2) + /* No PSEL for QSPI_V2, pins only controlled by CTRLSEL */ + case NRF_FUN_QSPI_SCK: + case NRF_FUN_QSPI_CSN: + case NRF_FUN_QSPI_IO0: + case NRF_FUN_QSPI_IO1: + case NRF_FUN_QSPI_IO2: + case NRF_FUN_QSPI_IO3: + nrf_gpio_pin_control_select(psel, NRF_GPIO_PIN_SEL_QSPI); + dir = NRF_GPIO_PIN_DIR_OUTPUT; + input = NRF_GPIO_PIN_INPUT_CONNECT; + break; +#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_qspi_v2) */ #if defined(NRF_PSEL_TWIS) case NRF_FUN_TWIS_SCL: NRF_PSEL_TWIS(reg, SCL) = psel; @@ -549,6 +530,37 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, input = NRF_GPIO_PIN_INPUT_CONNECT; break; #endif /* defined(NRF_PSEL_TWIS) */ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_coresight_nrf) + /* Pin routing is controlled by secure domain, via UICR */ + case NRF_FUN_TPIU_CLOCK: + case NRF_FUN_TPIU_DATA0: + case NRF_FUN_TPIU_DATA1: + case NRF_FUN_TPIU_DATA2: + case NRF_FUN_TPIU_DATA3: + dir = NRF_GPIO_PIN_DIR_OUTPUT; + input = NRF_GPIO_PIN_INPUT_DISCONNECT; + break; +#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_coresight_nrf) */ +#if defined(NRF_PSEL_SDP_MSPI) + case NRF_FUN_SDP_MSPI_CS0: + case NRF_FUN_SDP_MSPI_CS1: + case NRF_FUN_SDP_MSPI_CS2: + case NRF_FUN_SDP_MSPI_CS3: + case NRF_FUN_SDP_MSPI_CS4: + case NRF_FUN_SDP_MSPI_SCK: + case NRF_FUN_SDP_MSPI_DQ0: + case NRF_FUN_SDP_MSPI_DQ1: + case NRF_FUN_SDP_MSPI_DQ2: + case NRF_FUN_SDP_MSPI_DQ3: + case NRF_FUN_SDP_MSPI_DQ4: + case NRF_FUN_SDP_MSPI_DQ5: + case NRF_FUN_SDP_MSPI_DQ6: + case NRF_FUN_SDP_MSPI_DQ7: + NRF_PSEL_SDP_MSPI(psel); + dir = NRF_GPIO_PIN_DIR_OUTPUT; + input = NRF_GPIO_PIN_INPUT_CONNECT; + break; +#endif /* defined(NRF_PSEL_SDP_MSPI) */ default: return -ENOTSUP; } @@ -558,7 +570,7 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uint32_t pin = psel; /* enable pin */ - pad_group_request_pin(pin); + port_pin_retain_set(pin, false); if (write != NO_WRITE) { nrf_gpio_pin_write(pin, write); @@ -576,7 +588,7 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, if (NRF_GET_LP(pins[i]) == NRF_LP_ENABLE) { /* disable pin and pin clock */ - pad_group_release_pin(pin); + port_pin_retain_set(pin, true); port_pin_clock_set(pin, false); } else { /* configure pin clock */ diff --git a/drivers/power_domain/CMakeLists.txt b/drivers/power_domain/CMakeLists.txt index 357efe6f4ab7..2749a32d5d63 100644 --- a/drivers/power_domain/CMakeLists.txt +++ b/drivers/power_domain/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO_MONITOR power_domain_gpio_ zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_INTEL_ADSP power_domain_intel_adsp.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NXP_SCU power_domain_nxp_scu.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NRFS_GDPWR power_domain_nrfs_gdpwr.c) -zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NRF_GPIO_PAD_GROUP power_domain_nrf_gpio_pad_group.c) +zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NRFS_SWEXT power_domain_nrfs_swext.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_SOC_PM_STATE power_domain_soc_state_change.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_TISCI power_domain_tisci.c) +zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_SILABS_SIWX91X power_domain_silabs_siwx91x.c) diff --git a/drivers/power_domain/Kconfig b/drivers/power_domain/Kconfig index 7b336700dd6e..3de9185761c0 100644 --- a/drivers/power_domain/Kconfig +++ b/drivers/power_domain/Kconfig @@ -124,6 +124,7 @@ config SOC_POWER_DOMAIN_INIT endif #POWER_DOMAIN_TISCI rsource "Kconfig.nrfs_gdpwr" -rsource "Kconfig.nrf_gpio_pad_group" +rsource "Kconfig.nrfs_swext" +rsource "Kconfig.silabs_siwx91x" endif diff --git a/drivers/power_domain/Kconfig.nrf_gpio_pad_group b/drivers/power_domain/Kconfig.nrf_gpio_pad_group deleted file mode 100644 index 1b36c0cc7e08..000000000000 --- a/drivers/power_domain/Kconfig.nrf_gpio_pad_group +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright 2025 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -config POWER_DOMAIN_NRF_GPIO_PAD_GROUP - bool "NRFS Global Domain Power Request driver" - depends on DT_HAS_NORDIC_NRF_GPIO_PAD_GROUP_ENABLED - default y diff --git a/drivers/power_domain/Kconfig.nrfs_gdpwr b/drivers/power_domain/Kconfig.nrfs_gdpwr index bf9abd59aedb..c5f05d88a7ee 100644 --- a/drivers/power_domain/Kconfig.nrfs_gdpwr +++ b/drivers/power_domain/Kconfig.nrfs_gdpwr @@ -4,6 +4,7 @@ config POWER_DOMAIN_NRFS_GDPWR bool "NRFS Global Domain Power Request driver" depends on DT_HAS_NORDIC_NRFS_GDPWR_ENABLED + depends on MULTITHREADING select NRFS select NRFS_GDPWR_SERVICE_ENABLED default y diff --git a/drivers/power_domain/Kconfig.nrfs_swext b/drivers/power_domain/Kconfig.nrfs_swext new file mode 100644 index 000000000000..1a2c5d2d895e --- /dev/null +++ b/drivers/power_domain/Kconfig.nrfs_swext @@ -0,0 +1,9 @@ +# Copyright 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config POWER_DOMAIN_NRFS_SWEXT + bool "NRFS SWEXT power domain driver" + depends on DT_HAS_NORDIC_NRFS_SWEXT_ENABLED + select NRFS + select NRFS_SWEXT_SERVICE_ENABLED + default y diff --git a/drivers/power_domain/Kconfig.silabs_siwx91x b/drivers/power_domain/Kconfig.silabs_siwx91x new file mode 100644 index 000000000000..3fa95f335538 --- /dev/null +++ b/drivers/power_domain/Kconfig.silabs_siwx91x @@ -0,0 +1,16 @@ +# Copyright 2025 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +config POWER_DOMAIN_SILABS_SIWX91X + bool "Silabs siwx91x power domain driver" + default y + select DEVICE_DEPS + depends on DT_HAS_SILABS_SIWX91X_POWER_DOMAIN_ENABLED + help + Driver for Silabs siwx91x power domain. + +config SIWX91X_POWER_DOMAIN_INIT_PRIORITY + int "Silabs siwx91x power domain init priority" + default 10 + help + Silabs siwx91x power domain initialization priority. diff --git a/drivers/power_domain/power_domain_nrf_gpio_pad_group.c b/drivers/power_domain/power_domain_nrf_gpio_pad_group.c deleted file mode 100644 index 8b4119312c10..000000000000 --- a/drivers/power_domain/power_domain_nrf_gpio_pad_group.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT nordic_nrf_gpio_pad_group - -#include -#include -#include -#include - -#include - -LOG_MODULE_REGISTER(nrf_gpio_pad_group, CONFIG_POWER_DOMAIN_LOG_LEVEL); - -struct nrf_port_retain_config { - NRF_GPIO_Type *regs; - uint32_t retain_mask; -}; - -static void nrf_port_retain_driver_turn_off(const struct device *dev) -{ - const struct nrf_port_retain_config *dev_config = dev->config; - - LOG_DBG("%s pads 0x%08x retain %s", dev->name, dev_config->retain_mask, "enable"); - nrf_gpio_port_retain_enable(dev_config->regs, dev_config->retain_mask); -} - -static void nrf_port_retain_driver_turn_on(const struct device *dev) -{ - const struct nrf_port_retain_config *dev_config = dev->config; - - LOG_DBG("%s pads 0x%08x retain %s", dev->name, dev_config->retain_mask, "disable"); - nrf_gpio_port_retain_disable(dev_config->regs, dev_config->retain_mask); -} - -static int nrf_port_retain_driver_pm_action(const struct device *dev, - enum pm_device_action action) -{ - switch (action) { - case PM_DEVICE_ACTION_TURN_OFF: - nrf_port_retain_driver_turn_off(dev); - break; - - case PM_DEVICE_ACTION_TURN_ON: - nrf_port_retain_driver_turn_on(dev); - break; - - default: - break; - }; - - return 0; -} - -static int nrf_port_retain_driver_init(const struct device *dev) -{ - return pm_device_driver_init(dev, nrf_port_retain_driver_pm_action); -} - -#define NRF_GPIO_PAD_GROUP_DEFINE(inst) \ - static const struct nrf_port_retain_config _CONCAT(config, inst) = { \ - .regs = (NRF_GPIO_Type *)DT_REG_ADDR(DT_INST_PARENT(inst)), \ - .retain_mask = DT_PROP_OR(inst, retain_mask, UINT32_MAX), \ - }; \ - \ - PM_DEVICE_DT_INST_DEFINE(inst, nrf_port_retain_driver_pm_action); \ - \ - DEVICE_DT_INST_DEFINE( \ - inst, \ - nrf_port_retain_driver_init, \ - PM_DEVICE_DT_INST_GET(inst), \ - NULL, \ - &_CONCAT(config, inst), \ - PRE_KERNEL_1, \ - UTIL_INC(CONFIG_GPIO_INIT_PRIORITY), \ - NULL \ - ); - -DT_INST_FOREACH_STATUS_OKAY(NRF_GPIO_PAD_GROUP_DEFINE) diff --git a/drivers/power_domain/power_domain_nrfs_swext.c b/drivers/power_domain/power_domain_nrfs_swext.c new file mode 100644 index 000000000000..900fe4f7a8e6 --- /dev/null +++ b/drivers/power_domain/power_domain_nrfs_swext.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_nrfs_swext + +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(nrfs_swext, CONFIG_POWER_DOMAIN_LOG_LEVEL); + +BUILD_ASSERT( + DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, + "multiple instances not supported" +); + +struct nrfs_swext_data { + struct k_sem evt_sem; + nrfs_swext_evt_type_t evt; +}; + +struct nrfs_swext_config { + uint16_t current_limit_ua; + bool enable_power_down_clamp; +}; + +static void nrfs_swext_driver_evt_handler(nrfs_swext_evt_t const *p_evt, void *context) +{ + struct nrfs_swext_data *dev_data = context; + + LOG_DBG("evt %u", (uint32_t)p_evt->type); + + if (p_evt->type == NRFS_SWEXT_EVT_OVERCURRENT) { + /* Overcurrent is an unrecoverable condition which requires hardware fix */ + LOG_ERR("overcurrent"); + k_panic(); + }; + + dev_data->evt = p_evt->type; + k_sem_give(&dev_data->evt_sem); +} + +static int nrfs_swext_driver_power_down(const struct device *dev) +{ + const struct nrfs_swext_config *dev_config = dev->config; + nrfs_err_t err; + swext_pd_clamp_t pd_clamp = dev_config->enable_power_down_clamp + ? SWEXT_PD_CLAMP_ENABLED + : SWEXT_PD_CLAMP_DISABLED; + + /* + * Power down request does not respond with an event. + * Set context to NULL, fire and forget. + */ + err = nrfs_swext_power_down(pd_clamp, NULL); + if (err != NRFS_SUCCESS) { + LOG_ERR("failed to request power down"); + return -ENODEV; + } + + return 0; +} + +static int nrfs_swext_driver_power_up(const struct device *dev) +{ + struct nrfs_swext_data *dev_data = dev->data; + const struct nrfs_swext_config *dev_config = dev->config; + nrfs_err_t err; + uint8_t load_current; + + load_current = nrfs_swext_load_current_to_raw(dev_config->current_limit_ua); + err = nrfs_swext_power_up(load_current, dev_data); + if (err != NRFS_SUCCESS) { + LOG_ERR("failed to request power up"); + return -ENODEV; + } + + (void)k_sem_take(&dev_data->evt_sem, K_FOREVER); + + if (dev_data->evt == NRFS_SWEXT_EVT_ENABLED) { + return 0; + } + + LOG_ERR("power up request rejected"); + return -EIO; +} + +#if IS_ENABLED(CONFIG_DEVICE_DEPS) && IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN) +static void nrfs_swext_driver_notify_children(const struct device *dev, + enum pm_device_action action) +{ + pm_device_children_action_run(dev, action, NULL); +} +#else +static void nrfs_swext_driver_notify_children(const struct device *dev, + enum pm_device_action action) +{ + ARG_UNUSED(dev); + ARG_UNUSED(action); +} +#endif + +static int nrfs_swext_driver_suspend(const struct device *dev) +{ + int ret; + + nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_OFF); + + ret = nrfs_swext_driver_power_down(dev); + if (ret) { + nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_ON); + } + + return ret; +} + +static int nrfs_swext_driver_resume(const struct device *dev) +{ + int ret; + + ret = nrfs_swext_driver_power_up(dev); + if (ret == 0) { + nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_ON); + } + + return ret; +} + +static int nrfs_swext_driver_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + ret = nrfs_swext_driver_suspend(dev); + break; + + case PM_DEVICE_ACTION_RESUME: + ret = nrfs_swext_driver_resume(dev); + break; + + default: + ret = -ENOTSUP; + break; + }; + + return ret; +} + +static int nrfs_swext_driver_init(const struct device *dev) +{ + struct nrfs_swext_data *dev_data = dev->data; + nrfs_err_t err; + + LOG_DBG("waiting for nrfs backend connected"); + err = nrfs_backend_wait_for_connection(K_FOREVER); + if (err != NRFS_SUCCESS) { + LOG_ERR("nrfs backend not connected"); + return -ENODEV; + } + + err = nrfs_swext_init(nrfs_swext_driver_evt_handler); + if (err != NRFS_SUCCESS) { + LOG_ERR("failed to init swext service"); + return -ENODEV; + } + + k_sem_init(&dev_data->evt_sem, 0, 1); + return pm_device_driver_init(dev, nrfs_swext_driver_pm_action); +} + +PM_DEVICE_DT_INST_DEFINE(0, nrfs_swext_driver_pm_action); + +BUILD_ASSERT(DT_INST_PROP(0, max_current_ua) <= UINT16_MAX); +BUILD_ASSERT(DT_INST_PROP(0, current_limit_ua) <= DT_INST_PROP(0, max_current_ua)); + +static struct nrfs_swext_data data0; +static const struct nrfs_swext_config config0 = { + .current_limit_ua = DT_INST_PROP(0, current_limit_ua), + .enable_power_down_clamp = DT_INST_PROP(0, power_down_clamp), +}; + +DEVICE_DT_INST_DEFINE( + 0, + nrfs_swext_driver_init, + PM_DEVICE_DT_INST_GET(0), + &data0, + &config0, + POST_KERNEL, + UTIL_INC(CONFIG_NRFS_BACKEND_IPC_SERVICE_INIT_PRIO), + NULL +); diff --git a/drivers/power_domain/power_domain_silabs_siwx91x.c b/drivers/power_domain/power_domain_silabs_siwx91x.c new file mode 100644 index 000000000000..8350e8a25e15 --- /dev/null +++ b/drivers/power_domain/power_domain_silabs_siwx91x.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define DT_DRV_COMPAT silabs_siwx91x_power_domain + +static int siwx91x_pd_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_RESUME: + pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_ON, NULL); + break; + case PM_DEVICE_ACTION_SUSPEND: + pm_device_children_action_run(dev, PM_DEVICE_ACTION_TURN_OFF, NULL); + break; + case PM_DEVICE_ACTION_TURN_ON: + break; + case PM_DEVICE_ACTION_TURN_OFF: + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int siwx91x_pd_init(const struct device *dev) +{ + return pm_device_driver_init(dev, siwx91x_pd_pm_action); +} + +#define SIWX91X_PD_INIT(inst) \ + PM_DEVICE_DT_INST_DEFINE(inst, siwx91x_pd_pm_action); \ + DEVICE_DT_INST_DEFINE(inst, siwx91x_pd_init, PM_DEVICE_DT_INST_GET(inst), NULL, NULL, \ + PRE_KERNEL_1, CONFIG_SIWX91X_POWER_DOMAIN_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(SIWX91X_PD_INIT) diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index 8565fd1187ac..55a2b759b18b 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -13,7 +13,6 @@ #include #include #include -#include #include @@ -36,20 +35,6 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL); #define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx) #define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop) #define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop) -#define PWM_NRFX_IS_FAST(idx) NRF_DT_IS_FAST(PWM(idx)) - -#if NRF_DT_INST_ANY_IS_FAST -#define PWM_NRFX_FAST_PRESENT 1 -/* If fast instances are used then system managed device PM cannot be used because - * it may call PM actions from locked context and fast PWM PM actions can only be - * called in a thread context. - */ -BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED)); -#endif - -#if defined(PWM_NRFX_FAST_PRESENT) && CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL -#define PWM_NRFX_USE_CLOCK_CONTROL 1 -#endif #define PWM_NRFX_CH_POLARITY_MASK BIT(15) #define PWM_NRFX_CH_COMPARE_MASK BIT_MASK(15) @@ -65,10 +50,6 @@ struct pwm_nrfx_config { #ifdef CONFIG_DCACHE uint32_t mem_attr; #endif -#ifdef PWM_NRFX_USE_CLOCK_CONTROL - const struct device *clk_dev; - struct nrf_clock_spec clk_spec; -#endif }; struct pwm_nrfx_data { @@ -77,27 +58,12 @@ struct pwm_nrfx_data { uint8_t pwm_needed; uint8_t prescaler; bool stop_requested; -#ifdef PWM_NRFX_USE_CLOCK_CONTROL - bool clock_requested; -#endif }; /* Ensure the pwm_needed bit mask can accommodate all available channels. */ #if (NRF_PWM_CHANNEL_COUNT > 8) #error "Current implementation supports maximum 8 channels." #endif -#ifdef PWM_NRFX_FAST_PRESENT -static bool pwm_is_fast(const struct pwm_nrfx_config *config) -{ - return config->clock_freq > MHZ(16); -} -#else -static bool pwm_is_fast(const struct pwm_nrfx_config *config) -{ - return false; -} -#endif - static uint16_t *seq_values_ptr_get(const struct device *dev) { const struct pwm_nrfx_config *config = dev->config; @@ -178,21 +144,6 @@ static int stop_pwm(const struct device *dev) */ nrfx_pwm_stop(&config->pwm, false); -#if PWM_NRFX_USE_CLOCK_CONTROL - struct pwm_nrfx_data *data = dev->data; - - if (data->clock_requested) { - int ret = nrf_clock_control_release(config->clk_dev, &config->clk_spec); - - if (ret < 0) { - LOG_ERR("Global HSFLL release failed: %d", ret); - return ret; - } - - data->clock_requested = false; - } -#endif - return 0; } @@ -232,9 +183,8 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, /* Constantly active (duty 100%). */ /* This value is always greater than or equal to COUNTERTOP. */ compare_value = PWM_NRFX_CH_COMPARE_MASK; - needs_pwm = pwm_is_fast(config) || - (IS_ENABLED(NRF_PWM_HAS_IDLEOUT) && - IS_ENABLED(CONFIG_PWM_NRFX_NO_GLITCH_DUTY_100)); + needs_pwm = IS_ENABLED(NRF_PWM_HAS_IDLEOUT) && + IS_ENABLED(CONFIG_PWM_NRFX_NO_GLITCH_DUTY_100); } else { /* PWM generation needed. Check if the requested period matches * the one that is currently set, or the PWM peripheral can be @@ -290,22 +240,6 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, * registers and drives its outputs accordingly. */ if (data->pwm_needed == 0) { - if (pwm_is_fast(config)) { -#if PWM_NRFX_USE_CLOCK_CONTROL - if (data->clock_requested) { - int ret = nrf_clock_control_release(config->clk_dev, - &config->clk_spec); - - if (ret < 0) { - LOG_ERR("Global HSFLL release failed: %d", ret); - return ret; - } - - data->clock_requested = false; - } -#endif - return 0; - } int ret = stop_pwm(dev); if (ret < 0) { @@ -332,20 +266,6 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, * until another playback is requested (new values will be * loaded then) or the PWM peripheral is stopped. */ -#if PWM_NRFX_USE_CLOCK_CONTROL - if (config->clk_dev && !data->clock_requested) { - int ret = nrf_clock_control_request_sync(config->clk_dev, - &config->clk_spec, - K_FOREVER); - - if (ret < 0) { - LOG_ERR("Global HSFLL request failed: %d", ret); - return ret; - } - - data->clock_requested = true; - } -#endif nrfx_pwm_simple_playback(&config->pwm, &config->seq, 1, NRFX_PWM_FLAG_NO_EVT_FINISHED); } @@ -463,21 +383,6 @@ static int pwm_nrfx_init(const struct device *dev) COND_CODE_1(PWM_HAS_PROP(idx, memory_regions), \ (DT_PROP_OR(PWM_MEM_REGION(idx), zephyr_memory_attr, 0)), (0)) -/* Fast instances depend on the global HSFLL clock controller (as they need - * to request the highest frequency from it to operate correctly), so they - * must be initialized after that controller driver, hence the default PWM - * initialization priority may be too early for them. - */ -#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY) && \ - CONFIG_PWM_INIT_PRIORITY < CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY -#define PWM_INIT_PRIORITY(idx) \ - COND_CODE_1(PWM_NRFX_IS_FAST(idx), \ - (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \ - (CONFIG_PWM_INIT_PRIORITY)) -#else -#define PWM_INIT_PRIORITY(idx) CONFIG_PWM_INIT_PRIORITY -#endif - #define PWM_NRFX_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \ NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(PWM(idx)); \ @@ -506,14 +411,6 @@ static int pwm_nrfx_init(const struct device *dev) (16ul * 1000ul * 1000ul)), \ IF_ENABLED(CONFIG_DCACHE, \ (.mem_attr = PWM_GET_MEM_ATTR(idx),)) \ - IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \ - (.clk_dev = PWM_NRFX_IS_FAST(idx) \ - ? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \ - : NULL, \ - .clk_spec = { \ - .frequency = \ - NRF_PERIPH_GET_FREQUENCY(PWM(idx)), \ - },)) \ }; \ static int pwm_nrfx_init##idx(const struct device *dev) \ { \ @@ -526,7 +423,7 @@ static int pwm_nrfx_init(const struct device *dev) pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \ &pwm_nrfx_##idx##_data, \ &pwm_nrfx_##idx##_config, \ - POST_KERNEL, PWM_INIT_PRIORITY(idx), \ + POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ &pwm_nrfx_drv_api_funcs) #define COND_PWM_NRFX_DEVICE(unused, prefix, i, _) \ diff --git a/drivers/sensor/nordic/qdec_nrfx/qdec_nrfx.c b/drivers/sensor/nordic/qdec_nrfx/qdec_nrfx.c index 9ecfb5c122da..0d5eb5ab8cc2 100644 --- a/drivers/sensor/nordic/qdec_nrfx/qdec_nrfx.c +++ b/drivers/sensor/nordic/qdec_nrfx/qdec_nrfx.c @@ -272,6 +272,26 @@ static int qdec_nrfx_init(const struct device *dev) #define QDEC(idx) DT_NODELABEL(qdec##idx) #define QDEC_PROP(idx, prop) DT_PROP(QDEC(idx), prop) +/* Macro determines PM actions interrupt safety level. + * + * Requesting/releasing QDEC device may be ISR safe, but it cannot be reliably known whether + * managing its power domain is. It is then assumed that if power domains are used, device is + * no longer ISR safe. This macro let's us check if we will be requesting/releasing + * power domains and determines PM device ISR safety value. + */ +#define QDEC_PM_ISR_SAFE(idx) \ + COND_CODE_1( \ + UTIL_AND( \ + IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN), \ + UTIL_AND( \ + DT_NODE_HAS_PROP(QDEC(idx), power_domains), \ + DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE(QDEC(idx), power_domains)) \ + ) \ + ), \ + (0), \ + (PM_DEVICE_ISR_SAFE) \ + ) + #define SENSOR_NRFX_QDEC_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(QDEC(idx)); \ BUILD_ASSERT(QDEC_PROP(idx, steps) > 0, \ @@ -301,7 +321,7 @@ static int qdec_nrfx_init(const struct device *dev) .enable_pin = DT_PROP_OR(QDEC(idx), enable_pin, NRF_QDEC_PIN_NOT_CONNECTED), \ .steps = QDEC_PROP(idx, steps), \ }; \ - PM_DEVICE_DT_DEFINE(QDEC(idx), qdec_nrfx_pm_action, PM_DEVICE_ISR_SAFE); \ + PM_DEVICE_DT_DEFINE(QDEC(idx), qdec_nrfx_pm_action, QDEC_PM_ISR_SAFE(idx)); \ SENSOR_DEVICE_DT_DEFINE(QDEC(idx), \ qdec_nrfx_init, \ PM_DEVICE_DT_GET(QDEC(idx)), \ diff --git a/drivers/serial/Kconfig.nrfx b/drivers/serial/Kconfig.nrfx index 647e8cbb2e6f..722cc11da071 100644 --- a/drivers/serial/Kconfig.nrfx +++ b/drivers/serial/Kconfig.nrfx @@ -28,13 +28,6 @@ config UART_NRFX_UARTE imply NRFX_UARTE_CONFIG_SKIP_PSEL_CONFIG if !UART_NRFX_UARTE_LEGACY_SHIM imply NRFX_UARTE_CONFIG_SKIP_GPIO_CONFIG if !UART_NRFX_UARTE_LEGACY_SHIM -config UART_NRFX_UARTE_USE_CLOCK_CONTROL - def_bool y - depends on UART_NRFX_UARTE - depends on $(dt_nodelabel_enabled,uart120) - depends on !SOC_NRF54H20_CPUFLPR && !SOC_NRF54H20_CPUPPR - select CLOCK_CONTROL - config UART_NRFX_UARTE_NO_IRQ bool "Polling without interrupt" depends on UART_NRFX_UARTE @@ -79,6 +72,32 @@ config UART_ASYNC_TX_CACHE_SIZE in RAM, because EasyDMA in UARTE peripherals can only transfer data from RAM. +config UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + bool "Use TIMER to count RX bytes" + depends on UART_ASYNC_API + depends on UART_NRFX_UARTE_LEGACY_SHIM + depends on !ARCH_POSIX # Mode not supported on BSIM target + select NRFX_GPPI + +config UART_NRFX_UARTE_BOUNCE_BUF_LEN + int "RX bounce buffer size" + depends on UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + default 256 + range 64 1024 + help + Buffer is used when workaround with bounce buffers is applied + +config UART_NRFX_UARTE_BOUNCE_BUF_SWAP_LATENCY + int "RX bounce buffer swap latency (in microseconds)" + depends on UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + default 300 + help + Option decides how long before current bounce buffer is filled driver + attempts to swap the buffer. It must be long enough to ensure that + space following the buffer is not overwritten. Too high value results + in more frequent buffer swaps so it impacts performance. Setting should + take into account potential interrupt handling latency. + config UART_NRFX_UARTE_DIRECT_ISR bool "Use direct ISR" diff --git a/drivers/serial/Kconfig.nrfx_uart_instance b/drivers/serial/Kconfig.nrfx_uart_instance index b1a68d691c45..82ffaa10fcb9 100644 --- a/drivers/serial/Kconfig.nrfx_uart_instance +++ b/drivers/serial/Kconfig.nrfx_uart_instance @@ -18,6 +18,13 @@ config UART_$(nrfx_uart_num)_ASYNC help This option enables UART Asynchronous API support on port $(nrfx_uart_num). +config UART_$(nrfx_uart_num)_COUNT_BYTES_WITH_TIMER + bool + depends on $(dt_nodelabel_has_prop,uart$(nrfx_uart_num),timer) + depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) + default y + imply UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + config UART_$(nrfx_uart_num)_ENHANCED_POLL_OUT bool "Efficient poll out on port $(nrfx_uart_num)" depends on !$(dt_nodelabel_bool_prop,uart$(nrfx_uart_num),endtx-stoptx-supported) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index a5436eb0ec62..ffb090ca16f1 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -23,7 +23,6 @@ #include #include #include -#include LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); @@ -118,26 +117,6 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #define UARTE_ANY_LOW_POWER 1 #endif -/* Only cores with access to GDFS can control clocks and power domains, so if a fast instance is - * used by other cores, treat the UART like a normal one. This presumes cores with access to GDFS - * have requested the clocks and power domains needed by the fast instance to be ACTIVE before - * other cores use the fast instance. - */ -#if CONFIG_NRFS_GDFS_SERVICE_ENABLED -#define INSTANCE_IS_FAST(unused, prefix, idx, _) \ - UTIL_AND( \ - UTIL_AND( \ - IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##idx), \ - NRF_DT_IS_FAST(UARTE(idx)) \ - ), \ - IS_ENABLED(CONFIG_CLOCK_CONTROL) \ - ) - -#if UARTE_FOR_EACH_INSTANCE(INSTANCE_IS_FAST, (||), (0)) -#define UARTE_ANY_FAST 1 -#endif -#endif - #define INSTANCE_IS_HIGH_SPEED(unused, prefix, idx, _) \ COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(prefix##idx)), \ ((NRF_PERIPH_GET_FREQUENCY(UARTE(prefix##idx)) > NRF_UARTE_BASE_FREQUENCY_16MHZ)), \ @@ -148,27 +127,6 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); */ #define UARTE_ANY_HIGH_SPEED (UARTE_FOR_EACH_INSTANCE(INSTANCE_IS_HIGH_SPEED, (||), (0))) -#define UARTE_PINS_CROSS_DOMAIN(unused, prefix, idx, _) \ - COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(prefix##idx)), \ - (UARTE_PROP(idx, cross_domain_pins_supported)), \ - (0)) - -#if UARTE_FOR_EACH_INSTANCE(UARTE_PINS_CROSS_DOMAIN, (||), (0)) -#include -/* Certain UARTE instances support usage of cross domain pins in form of dedicated pins on - * a port different from the default one. - */ -#define UARTE_CROSS_DOMAIN_PINS_SUPPORTED 1 -#endif - -#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED && defined(CONFIG_NRF_SYS_EVENT) -#include -/* To use cross domain pins, constant latency mode needs to be applied, which is - * handled via nrf_sys_event requests. - */ -#define UARTE_CROSS_DOMAIN_PINS_HANDLE 1 -#endif - #ifdef UARTE_ANY_CACHE /* uart120 instance does not retain BAUDRATE register when ENABLE=0. When this instance * is used then baudrate must be set after enabling the peripheral and not before. @@ -188,6 +146,16 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); /* Size of hardware fifo in RX path. */ #define UARTE_HW_RX_FIFO_SIZE 5 +/* TIMER CC channels for counting bytes with TIMER. */ +/* Channel used for capturing current counter value. */ +#define UARTE_TIMER_CAPTURE_CH 0 +/* Channel used to get compare event when number of received bytes reaches user buffer size. */ +#define UARTE_TIMER_USR_CNT_CH 1 +/* Channel used to get compare event when bounce buffer need to be switched. */ +#define UARTE_TIMER_BUF_SWITCH_CH 2 +/* Magic byte that is used to fill the buffer. */ +#define UARTE_MAGIC_BYTE 0xAA + #ifdef UARTE_ANY_ASYNC struct uarte_async_tx { @@ -201,6 +169,30 @@ struct uarte_async_tx { bool pending; }; +/* Structure with data for Count Bytes With Timer receiver mode (cbwt). */ +struct uarte_async_rx_cbwt { + uint8_t *curr_bounce_buf; + uint8_t *anomaly_byte_addr; + uint32_t usr_rd_off; + uint32_t usr_wr_off; + uint32_t bounce_off; + uint32_t bounce_limit; + uint32_t last_cnt; + uint32_t cc_usr; + uint32_t cc_swap; +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + size_t bounce_buf_swap_len; +#endif +#ifdef UARTE_ANY_CACHE + uint8_t *anomaly_byte_dst; + uint8_t anomaly_byte; +#endif + uint8_t bounce_idx; + uint8_t ppi_ch; + bool in_irq; + bool discard_fifo; +}; + struct uarte_async_rx { struct k_timer timer; #ifdef CONFIG_HAS_NORDIC_DMM @@ -212,8 +204,9 @@ struct uarte_async_rx { size_t offset; uint8_t *next_buf; size_t next_buf_len; -#ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX -#if !defined(UARTE_HAS_FRAME_TIMEOUT) +#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) || \ + defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) +#if !defined(UARTE_HAS_FRAME_TIMEOUT) || defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) uint32_t idle_cnt; #endif k_timeout_t timeout; @@ -286,6 +279,10 @@ struct uarte_nrfx_data { #define UARTE_FLAG_POLL_OUT BIT(3) /* Flag indicating that a workaround for not working frame timeout is active. */ #define UARTE_FLAG_FTIMEOUT_WATCH BIT(4) +/* Flag indicating that UART_RX_BUF_REQUEST event need to be called from the interrupt context. */ +#define UARTE_FLAG_RX_BUF_REQ BIT(5) +/* Flag indicating that CC value in TIMER was set too late. */ +#define UARTE_FLAG_LATE_CC BIT(6) /* If enabled then ENDTX is PPI'ed to TXSTOP */ #define UARTE_CFG_FLAG_PPI_ENDTX BIT(0) @@ -304,6 +301,12 @@ struct uarte_nrfx_data { /* Indicates that workaround for spurious RXTO during restart shall be applied. */ #define UARTE_CFG_FLAG_SPURIOUS_RXTO BIT(3) +/* Indicates that UARTE/TIMER interrupt priority differs from system clock (GRTC/RTC). */ +#define UARTE_CFG_FLAG_VAR_IRQ BIT(4) + +/* Indicates that instance needs special handling of BAUDRATE register. */ +#define UARTE_CFG_FLAG_VOLATILE_BAUDRATE BIT(5) + /* Formula for getting the baudrate settings is following: * 2^12 * (2^20 / (f_PCLK / desired_baudrate)) where f_PCLK is a frequency that * drives the UARTE. @@ -340,25 +343,19 @@ struct uarte_nrfx_data { (baudrate) == 921600 ? NRF_UARTE_BAUDRATE_921600 : \ (baudrate) == 1000000 ? NRF_UARTE_BAUDRATE_1000000 : 0) +#define UARTE_MIN_BUF_SWAP_LEN 10 + +#define UARTE_US_TO_BYTES(baudrate) \ + DIV_ROUND_UP((CONFIG_UART_NRFX_UARTE_BOUNCE_BUF_SWAP_LATENCY * baudrate), 10000000) + +#define UARTE_BUF_SWAP_LEN(bounce_buf_len, baudrate) \ + ((bounce_buf_len) - MAX(UARTE_MIN_BUF_SWAP_LEN, UARTE_US_TO_BYTES(baudrate))) + #define LOW_POWER_ENABLED(_config) \ (IS_ENABLED(UARTE_ANY_LOW_POWER) && \ !IS_ENABLED(CONFIG_PM_DEVICE) && \ (_config->flags & UARTE_CFG_FLAG_LOW_POWER)) -/** @brief Check if device has PM that works in ISR safe mode. - * - * Only fast UARTE instance does not work in that mode so check PM configuration - * flags only if there is any fast instance present. - * - * @retval true if device PM is ISR safe. - * @retval false if device PM is not ISR safe. - */ -#define IS_PM_ISR_SAFE(dev) \ - (!IS_ENABLED(UARTE_ANY_FAST) ||\ - COND_CODE_1(CONFIG_PM_DEVICE,\ - ((dev->pm_base->flags & BIT(PM_DEVICE_FLAG_ISR_SAFE))), \ - (0))) - /** * @brief Structure for UARTE configuration. */ @@ -370,10 +367,6 @@ struct uarte_nrfx_config { #ifdef CONFIG_HAS_NORDIC_DMM void *mem_reg; #endif -#ifdef UARTE_ANY_FAST - const struct device *clk_dev; - struct nrf_clock_spec clk_spec; -#endif #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE /* None-zero in case of high speed instances. Baudrate is adjusted by that ratio. */ uint32_t clock_freq; @@ -386,16 +379,21 @@ struct uarte_nrfx_config { #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ #ifdef UARTE_ANY_ASYNC +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + NRF_TIMER_Type * timer_regs; + IRQn_Type timer_irqn; + IRQn_Type uarte_irqn; + uint8_t *bounce_buf[2]; + size_t bounce_buf_len; + size_t bounce_buf_swap_len; + struct uarte_async_rx_cbwt *cbwt_data; +#endif nrfx_timer_t timer; uint8_t *tx_cache; uint8_t *rx_flush_buf; #endif uint8_t *poll_out_byte; uint8_t *poll_in_byte; -#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED - bool cross_domain; - int8_t default_port; -#endif }; /* Using Macro instead of static inline function to handle NO_OPTIMIZATIONS case @@ -405,6 +403,12 @@ struct uarte_nrfx_config { (IS_ENABLED(UARTE_ANY_HW_ASYNC) ? \ (config->flags & UARTE_CFG_FLAG_HW_BYTE_COUNTING) : false) +/* Determine if instance is using an approach with counting bytes with TIMER (cbwt). */ +#define IS_CBWT(dev) \ + COND_CODE_1(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER, \ + ((((const struct uarte_nrfx_config *)dev->config)->cbwt_data != NULL)), \ + (false)) + static inline NRF_UARTE_Type *get_uarte_instance(const struct device *dev) { const struct uarte_nrfx_config *config = dev->config; @@ -464,32 +468,6 @@ static void uarte_disable_locked(const struct device *dev, uint32_t dis_mask) (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); } -#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED -static bool uarte_has_cross_domain_connection(const struct uarte_nrfx_config *config) -{ - const struct pinctrl_dev_config *pcfg = config->pcfg; - const struct pinctrl_state *state; - int ret; - - ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state); - if (ret < 0) { - LOG_ERR("Unable to read pin state"); - return false; - } - - for (uint8_t i = 0U; i < state->pin_cnt; i++) { - uint32_t pin = NRF_GET_PIN(state->pins[i]); - - if ((pin != NRF_PIN_DISCONNECTED) && - (nrf_gpio_pin_port_number_extract(&pin) != config->default_port)) { - return true; - } - } - - return false; -} -#endif - #if defined(UARTE_ANY_NONE_ASYNC) && !defined(CONFIG_UART_NRFX_UARTE_NO_IRQ) /** * @brief Interrupt service routine. @@ -596,10 +574,23 @@ static int baudrate_set(const struct device *dev, uint32_t baudrate) return -EINVAL; } +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev)) { + struct uarte_async_rx_cbwt *cbwt_data = config->cbwt_data; + + cbwt_data->bounce_buf_swap_len = UARTE_BUF_SWAP_LEN(config->bounce_buf_len, + baudrate); + } +#endif + #ifdef UARTE_BAUDRATE_RETENTION_WORKAROUND - struct uarte_nrfx_data *data = dev->data; + if (config->flags & UARTE_CFG_FLAG_VOLATILE_BAUDRATE) { + struct uarte_nrfx_data *data = dev->data; - data->nrf_baudrate = nrf_baudrate; + data->nrf_baudrate = nrf_baudrate; + } else { + nrf_uarte_baudrate_set(get_uarte_instance(dev), nrf_baudrate); + } #else nrf_uarte_baudrate_set(get_uarte_instance(dev), nrf_baudrate); #endif @@ -759,37 +750,16 @@ static void uarte_periph_enable(const struct device *dev) struct uarte_nrfx_data *data = dev->data; (void)data; -#ifdef UARTE_ANY_FAST - if (config->clk_dev) { - int err; - - err = nrf_clock_control_request_sync(config->clk_dev, &config->clk_spec, K_FOREVER); - (void)err; - __ASSERT_NO_MSG(err >= 0); - } -#endif (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); nrf_uarte_enable(uarte); -#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED - if (config->cross_domain && uarte_has_cross_domain_connection(config)) { -#if UARTE_CROSS_DOMAIN_PINS_HANDLE - int err; - - err = nrf_sys_event_request_global_constlat(); - (void)err; - __ASSERT_NO_MSG(err >= 0); -#else - __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); -#endif - } -#endif - #if UARTE_BAUDRATE_RETENTION_WORKAROUND - nrf_uarte_baudrate_set(uarte, - COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, - (data->nrf_baudrate), (config->nrf_baudrate))); + if (config->flags & UARTE_CFG_FLAG_VOLATILE_BAUDRATE) { + nrf_uarte_baudrate_set(uarte, + COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, + (data->nrf_baudrate), (config->nrf_baudrate))); + } #endif #ifdef UARTE_ANY_ASYNC @@ -819,101 +789,850 @@ static void uarte_periph_enable(const struct device *dev) } } -static void uarte_enable_locked(const struct device *dev, uint32_t act_mask) +static void uarte_enable_locked(const struct device *dev, uint32_t act_mask) +{ + struct uarte_nrfx_data *data = dev->data; + bool already_active = (data->flags & UARTE_FLAG_LOW_POWER) != 0; + + data->flags |= act_mask; + if (already_active) { + /* Second direction already enabled so UARTE is enabled. */ + return; + } + + uarte_periph_enable(dev); +} + +/* At this point we should have irq locked and any previous transfer completed. + * Transfer can be started, no need to wait for completion. + */ +static void tx_start(const struct device *dev, const uint8_t *buf, size_t len) +{ + const struct uarte_nrfx_config *config = dev->config; + NRF_UARTE_Type *uarte = get_uarte_instance(dev); + +#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME) + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return; + } +#endif + + if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_flush_range((void *)buf, len); + } + + nrf_uarte_tx_buffer_set(uarte, buf, len); + if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT)) { + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX); + } + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED); + + if (LOW_POWER_ENABLED(config)) { + uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_TX); + } + nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX); +} + +#if defined(UARTE_ANY_ASYNC) +static void rx_timeout(struct k_timer *timer); +static void tx_timeout(struct k_timer *timer); + +static void user_callback(const struct device *dev, struct uart_event *evt) +{ + struct uarte_nrfx_data *data = dev->data; + + if (data->async->user_callback) { + data->async->user_callback(dev, evt, data->async->user_data); + } +} + +static void rx_buf_release(const struct device *dev, uint8_t *buf) +{ + struct uart_event evt = { + .type = UART_RX_BUF_RELEASED, + .data.rx_buf.buf = buf, + }; + + user_callback(dev, &evt); +} + +static void rx_disable_finalize(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uart_event evt = { + .type = UART_RX_DISABLED, + }; + + async_rx->enabled = false; + + if (LOW_POWER_ENABLED(cfg)) { + uint32_t key = irq_lock(); + + uarte_disable_locked(dev, UARTE_FLAG_LOW_POWER_RX); + irq_unlock(key); + } + + user_callback(dev, (struct uart_event *)&evt); + + /* runtime PM is put after the callback. In case uart is re-enabled from that + * callback we avoid suspending/resuming the device. + */ + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + pm_device_runtime_put_async(dev, K_NO_WAIT); + } +} + +static int rx_disable(const struct device *dev, bool api) +{ + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + NRF_UARTE_Type *uarte = get_uarte_instance(dev); + int key; + + k_timer_stop(&async_rx->timer); + + key = irq_lock(); + +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + if (cbwt_data) { + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_BUF_SWITCH_CH)); + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_USR_CNT_CH)); + nrf_timer_int_disable(cfg->timer_regs, + nrf_timer_compare_int_get(UARTE_TIMER_BUF_SWITCH_CH) | + nrf_timer_compare_int_get(UARTE_TIMER_USR_CNT_CH)); + nrf_uarte_shorts_disable(cfg->uarte_regs, NRF_UARTE_SHORT_ENDRX_STARTRX); + } +#endif + + if (async_rx->next_buf != NULL) { + nrf_uarte_shorts_disable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); + } + + async_rx->enabled = false; + if (api) { + async_rx->discard_fifo = true; + } + + nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX); + irq_unlock(key); + + return 0; +} + +static int uarte_nrfx_rx_disable(const struct device *dev) +{ + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + + if (async_rx->buf == NULL) { + return -EFAULT; + } + + return rx_disable(dev, true); +} + +#if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) +static void timer_handler(nrf_timer_event_t event_type, void *p_context) { } + +static int uarte_nrfx_rx_counting_init(const struct device *dev) +{ + struct uarte_nrfx_data *data = dev->data; + const struct uarte_nrfx_config *cfg = dev->config; + NRF_UARTE_Type *uarte = get_uarte_instance(dev); + int ret; + + if (HW_RX_COUNTING_ENABLED(cfg)) { + nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG( + NRF_TIMER_BASE_FREQUENCY_GET(cfg->timer.p_reg)); + uint32_t evt_addr = nrf_uarte_event_address_get(uarte, NRF_UARTE_EVENT_RXDRDY); + uint32_t tsk_addr = nrfx_timer_task_address_get(&cfg->timer, NRF_TIMER_TASK_COUNT); + + tmr_config.mode = NRF_TIMER_MODE_COUNTER; + tmr_config.bit_width = NRF_TIMER_BIT_WIDTH_32; + ret = nrfx_timer_init(&cfg->timer, + &tmr_config, + timer_handler); + if (ret != NRFX_SUCCESS) { + LOG_ERR("Timer already initialized"); + return -EINVAL; + } + + nrfx_timer_clear(&cfg->timer); + + ret = nrfx_gppi_channel_alloc(&data->async->rx.cnt.ppi); + if (ret != NRFX_SUCCESS) { + LOG_ERR("Failed to allocate PPI Channel"); + nrfx_timer_uninit(&cfg->timer); + return -EINVAL; + } + + nrfx_gppi_channel_endpoints_setup(data->async->rx.cnt.ppi, evt_addr, tsk_addr); + nrfx_gppi_channels_enable(BIT(data->async->rx.cnt.ppi)); + } else { + nrf_uarte_int_enable(uarte, NRF_UARTE_INT_RXDRDY_MASK); + } + + return 0; +} +#endif /* !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) */ + +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + +static uint32_t get_byte_cnt(NRF_TIMER_Type *timer) +{ + nrf_timer_task_trigger(timer, nrf_timer_capture_task_get(UARTE_TIMER_CAPTURE_CH)); + + nrf_barrier_w(); + + return nrf_timer_cc_get(timer, UARTE_TIMER_CAPTURE_CH); +} + +static void rx_buf_req(const struct device *dev) +{ + struct uart_event evt = { + .type = UART_RX_BUF_REQUEST, + }; + + user_callback(dev, &evt); +} + +static bool notify_rx_rdy(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + size_t len = cbwt_data->usr_wr_off - cbwt_data->usr_rd_off; + + if (len == 0) { + return async_rx->buf != NULL; + } + + struct uart_event evt = { + .type = UART_RX_RDY, + .data.rx.buf = async_rx->buf, + .data.rx.len = len, + .data.rx.offset = cbwt_data->usr_rd_off + }; + user_callback(dev, &evt); + cbwt_data->usr_rd_off += len; + + if (cbwt_data->usr_rd_off == async_rx->buf_len) { + rx_buf_release(dev, async_rx->buf); + async_rx->buf = async_rx->next_buf; + async_rx->buf_len = async_rx->next_buf_len; + async_rx->next_buf_len = 0; + async_rx->next_buf = 0; + cbwt_data->usr_rd_off = 0; + cbwt_data->usr_wr_off = 0; + + if (async_rx->buf_len == 0) { + return false; + } + + /* Set past value to ensure that event will not expire after clearing but + * before setting the new value. + */ + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_USR_CNT_CH, cbwt_data->cc_usr - 1); + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_USR_CNT_CH)); + cbwt_data->cc_usr += async_rx->buf_len; + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_USR_CNT_CH, cbwt_data->cc_usr); + + /* Check if CC is already in the past. In that case trigger CC handling.*/ + if (cbwt_data->cc_usr <= get_byte_cnt(cfg->timer_regs)) { + atomic_or(&data->flags, UARTE_FLAG_LATE_CC); + NRFX_IRQ_PENDING_SET(cfg->timer_irqn); + } else { + atomic_and(&data->flags, ~UARTE_FLAG_LATE_CC); + } + } + + return true; +} + +static void anomaly_byte_handle(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint8_t curr_byte, anomaly_byte; + uint32_t diff; + + if (cbwt_data->anomaly_byte_addr == NULL) { + return; + } + + diff = cfg->uarte_regs->DMA.RX.PTR - (uint32_t)cbwt_data->curr_bounce_buf; + /* Anomaly can be checked only if more than 1 byte is received to the current buffer. */ + if (diff < 2) { + return; + } + + if (IS_ENABLED(UARTE_ANY_CACHE) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_invd_range(cbwt_data->curr_bounce_buf, 1); + sys_cache_data_invd_range(cbwt_data->anomaly_byte_addr, 1); + } + + curr_byte = cbwt_data->curr_bounce_buf[0]; + anomaly_byte = *cbwt_data->anomaly_byte_addr; + if ((curr_byte == UARTE_MAGIC_BYTE) && (anomaly_byte != UARTE_MAGIC_BYTE)) { +#ifdef UARTE_ANY_CACHE + if (cfg->flags & UARTE_CFG_FLAG_CACHEABLE) { + /* We cannot write directly to curr_bounce_buf as it is written by + * DMA and with cache operations data may be overwritten. Copying + * need to be postponed to the moment when user buffer is filled. + */ + cbwt_data->anomaly_byte = anomaly_byte; + cbwt_data->anomaly_byte_dst = &cbwt_data->curr_bounce_buf[0]; + } else { + cbwt_data->curr_bounce_buf[0] = anomaly_byte; + } +#else + cbwt_data->curr_bounce_buf[0] = anomaly_byte; +#endif + } + + cbwt_data->anomaly_byte_addr = NULL; +} + +static uint32_t fill_usr_buf(const struct device *dev, uint32_t len) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + uint8_t *buf = cfg->bounce_buf[cbwt_data->bounce_idx]; + uint32_t usr_rem = async_rx->buf_len - cbwt_data->usr_wr_off; + uint32_t bounce_rem = cbwt_data->bounce_limit - cbwt_data->bounce_off; + uint32_t cpy_len = MIN(bounce_rem, MIN(usr_rem, len)); + + __ASSERT(cpy_len + cbwt_data->bounce_off <= cfg->bounce_buf_len, + "Exceeding the buffer cpy_len:%d off:%d limit:%d", + cpy_len, cbwt_data->bounce_off, cbwt_data->bounce_limit); + + if (IS_ENABLED(UARTE_ANY_CACHE) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_invd_range(&buf[cbwt_data->bounce_off], cpy_len); + } + + memcpy(&async_rx->buf[cbwt_data->usr_wr_off], &buf[cbwt_data->bounce_off], cpy_len); +#ifdef UARTE_ANY_CACHE + if ((buf == cbwt_data->anomaly_byte_dst) && (cbwt_data->bounce_off == 0)) { + async_rx->buf[cbwt_data->usr_wr_off] = cbwt_data->anomaly_byte; + cbwt_data->anomaly_byte_dst = NULL; + } +#endif + cbwt_data->bounce_off += cpy_len; + cbwt_data->usr_wr_off += cpy_len; + cbwt_data->last_cnt += cpy_len; + if (cbwt_data->bounce_off == cbwt_data->bounce_limit) { + /* Bounce buffer drained */ + cbwt_data->bounce_idx = cbwt_data->bounce_idx == 0 ? 1 : 0; + cbwt_data->bounce_off = 0; + cbwt_data->bounce_limit = cfg->bounce_buf_len; + } + + return cpy_len; +} + +static bool update_usr_buf(const struct device *dev, uint32_t len, bool notify_any, bool buf_req) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + anomaly_byte_handle(dev); + + do { + uint32_t cpy_len = len ? fill_usr_buf(dev, len) : 0; + bool usr_buf_full = cbwt_data->usr_wr_off == async_rx->buf_len; + + len -= cpy_len; + if (((len == 0) && notify_any) || usr_buf_full) { + if (!notify_rx_rdy(dev)) { + return false; + } + + if (usr_buf_full && buf_req) { + rx_buf_req(dev); + } + } + } while (len > 0); + + return true; +} + +static void prepare_bounce_buf(const struct device *dev, uint8_t *buf, + size_t swap_len, size_t len) +{ + const struct uarte_nrfx_config *cfg = dev->config; + + buf[0] = UARTE_MAGIC_BYTE; + for (size_t i = swap_len; i < len; i++) { + buf[i] = UARTE_MAGIC_BYTE; + } + + if (IS_ENABLED(UARTE_ANY_CACHE) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_flush_range(buf, 1); + sys_cache_data_flush_range(&buf[swap_len], len); + } +} + +/* This function is responsible for swapping the bounce buffer and it is the most + * tricky part of the solution. Receiver is continuously working and we want to + * change DMA pointer on the fly. DMA is also incrementing that pointer so there are + * moments in the reception when updating the pointer will result in different behavior. + * + * There are two main cases that need to be handled: + * 1. PTR is updated and there was no byte boundary (in the middle of a byte or there is + * no byte on the line). It is a safe spot. + * + * The most common and simplest case. PTR is update but since + * DMA already started the reception of the previous byte it means that next byte will + * be stored in the previous PTR and bytes following that byte will be stored to the + * new bounce buffer + * + * 2. Updating the pointer collided with byte boundary. + * + * RXDRDY and RXSTARTED events are used to detect if collision occurred. + * There are few scenarios that may happen and the driver must detect which one occurred. + * Detection is done by reading back the PTR register. Following cases are considered: + * + * - PTR did not change. It means that it was written after byte boundary. It is the same + * case as if PTR was updated in the safe spot. + * + * - PTR is updated by 1. There is an anomaly and it is unclear where next byte will be + * copied. PTR state indicates that it should be copied to the beginning of the new + * bounce buffer but it might be copied to the previous bounce buffer. Both locations + * are written with a magic byte (0xAA) and later on it is checked which location has + * changed and if byte was written to the previous bounce buffer it is copied to the + * start of the new bounce buffer. + * + * - PTR is not updated with the new bounce buffer location. DMA is incrementing PTR content + * and it is possible that SW writes new value between read and modify and DMA may + * overwrite value written by the driver. In that case reception continuous to the + * previous bounce buffer and swap procedure need to be repeated. + */ +static int bounce_buf_swap(const struct device *dev, uint8_t *prev_bounce_buf) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t prev_buf_cnt, new_cnt, cnt, ptr; + uint32_t prev_buf_inc = 1; + int key; + + key = irq_lock(); + /* Clear events that indicates byte boundary and set PTR. If events are set + * after PTR is set then we know that setting PTR collided with byte boundary. + */ + nrf_uarte_event_clear(cfg->uarte_regs, NRF_UARTE_EVENT_RXSTARTED); + nrf_uarte_event_clear(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY); + cfg->uarte_regs->DMA.RX.PTR = (uint32_t)cbwt_data->curr_bounce_buf; + cnt = get_byte_cnt(cfg->timer_regs); + + if (!nrf_uarte_event_check(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY) && + !nrf_uarte_event_check(cfg->uarte_regs, NRF_UARTE_EVENT_RXSTARTED)) { + /* RXDRDY did not happen when PTR was set. Safest case. PTR was updated + * correctly. Last byte will be received to the previous buffer. + */ + new_cnt = 0; + prev_buf_cnt = cnt - cbwt_data->last_cnt; + goto no_collision; + } + + /* Setting PTR collided with byte boundary we need to detect what happened. */ + while (!nrf_uarte_event_check(cfg->uarte_regs, NRF_UARTE_EVENT_RXSTARTED)) { + } + + /* Read pointer when there is no new byte coming. */ + do { + cnt = get_byte_cnt(cfg->timer_regs); + ptr = cfg->uarte_regs->DMA.RX.PTR; + } while (cnt != get_byte_cnt(cfg->timer_regs)); + + new_cnt = ptr - (uint32_t)cbwt_data->curr_bounce_buf; + prev_buf_cnt = cnt - cbwt_data->last_cnt; + + if (new_cnt == 0) { + /* New PTR is not incremented. It was written after LIST post ENDRX + * incrementation. + */ + } else if (new_cnt == 1) { + /* new_cnt == 1. New PTR incremented. It's possible that data is already + * copied to that new location or it is written to the tail of the previous + * bounce buffer. We try to detect what happens. + */ + prev_buf_inc = 0; + cbwt_data->anomaly_byte_addr = + &prev_bounce_buf[cbwt_data->bounce_off + prev_buf_cnt]; + } else if (new_cnt <= cfg->bounce_buf_len) { + prev_buf_inc = 0; + prev_buf_cnt = cnt - cbwt_data->last_cnt - (new_cnt - 1); + } else { + /* New PTR value is not set. Re-set PTR is needed. Transfer continues to + * previous buffer whole buffer swapping need to be repeat. + */ + irq_unlock(key); + return -EAGAIN; + } + +no_collision: + cbwt_data->bounce_limit = cbwt_data->bounce_off + prev_buf_cnt + prev_buf_inc; + __ASSERT(cbwt_data->bounce_limit < cfg->bounce_buf_len, + "Too high limit (%d, max:%d), increase latency", + cbwt_data->bounce_limit, cfg->bounce_buf_len); + irq_unlock(key); + + return prev_buf_cnt; +} + +static size_t get_swap_len(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + return cbwt_data->bounce_buf_swap_len; +#else + return cfg->bounce_buf_swap_len; +#endif +} + +static void bounce_buf_switch(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + int new_data = cbwt_data->cc_swap - cbwt_data->last_cnt; + uint8_t *prev_bounce_buf = cbwt_data->curr_bounce_buf; + int prev_cnt; + + /* Fill user buffer with all pending data. */ + if (!update_usr_buf(dev, new_data < 0 ? 0 : new_data, false, true)) { + rx_disable(dev, false); + return; + } + + cbwt_data->curr_bounce_buf = (cbwt_data->curr_bounce_buf == cfg->bounce_buf[0]) ? + cfg->bounce_buf[1] : cfg->bounce_buf[0]; + prepare_bounce_buf(dev, cbwt_data->curr_bounce_buf, get_swap_len(dev), + cfg->bounce_buf_len); + + /* Swapping may need retry. */ + while ((prev_cnt = bounce_buf_swap(dev, prev_bounce_buf)) < 0) { + } + + /* Update user buffer with data that was received during swapping. */ + if (update_usr_buf(dev, prev_cnt, false, true)) { + /* Set compare event for next moment when bounce buffers need to be swapped. */ + cbwt_data->cc_swap += get_swap_len(dev); + __ASSERT(cbwt_data->cc_swap > get_byte_cnt(cfg->timer_regs), + "Setting CC too late next:%d cnt:%d", + cbwt_data->cc_swap, get_byte_cnt(cfg->timer_regs)); + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_BUF_SWITCH_CH, cbwt_data->cc_swap); + } else { + /* Stop RX. */ + rx_disable(dev, false); + } +} + +static void usr_buf_complete(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t rem = async_rx->buf_len - cbwt_data->usr_wr_off; + + __ASSERT_NO_MSG(rem <= (get_byte_cnt(cfg->timer_regs) - cbwt_data->last_cnt)); + + if (!update_usr_buf(dev, rem, true, true)) { + /* Stop RX if there is no next buffer. */ + rx_disable(dev, false); + } +} + +static void notify_new_data(const struct device *dev, bool buf_req) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t cnt = get_byte_cnt(cfg->timer_regs); + uint32_t new_data = cnt - cbwt_data->last_cnt; + + (void)update_usr_buf(dev, new_data, true, buf_req); +} + +static void cbwt_rx_timeout(struct k_timer *timer) +{ + const struct device *dev = k_timer_user_data_get(timer); + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + struct uarte_async_rx *async_rx = &data->async->rx; + + if (nrf_uarte_event_check(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY)) { + nrf_uarte_event_clear(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY); + async_rx->idle_cnt = 0; + } else { + async_rx->idle_cnt++; + if (async_rx->idle_cnt == (RX_TIMEOUT_DIV - 1)) { + if (cfg->flags & UARTE_CFG_FLAG_VAR_IRQ) { + if (cbwt_data->in_irq) { + /* TIMER or UARTE interrupt preempted. Lets try again + * later. + */ + k_timer_start(timer, async_rx->timeout, K_NO_WAIT); + return; + } + irq_disable(cfg->uarte_irqn); + irq_disable(cfg->timer_irqn); + } + + nrf_uarte_int_enable(cfg->uarte_regs, NRF_UARTE_INT_RXDRDY_MASK); + notify_new_data(dev, true); + + if (cfg->flags & UARTE_CFG_FLAG_VAR_IRQ) { + irq_enable(cfg->uarte_irqn); + irq_enable(cfg->timer_irqn); + } + return; + } + } + + k_timer_start(timer, async_rx->timeout, K_NO_WAIT); +} + +static void cbwt_rx_flush_handle(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + NRF_UARTE_Type *uarte = get_uarte_instance(dev); + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t rem_data = get_byte_cnt(cfg->timer_regs) - cbwt_data->last_cnt; + uint32_t bbuf_rem_data = cbwt_data->bounce_limit - cbwt_data->bounce_off; + uint32_t amount; + uint8_t *dst; + + nrf_uarte_rx_buffer_set(uarte, cfg->rx_flush_buf, UARTE_HW_RX_FIFO_SIZE); + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); + nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_FLUSHRX); + while (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDRX)) { + /* empty */ + } + + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX); + if (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXSTARTED)) { + /* FIFO is empty. */ + return; + } + + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); + amount = nrf_uarte_rx_amount_get(uarte); + + if (rem_data <= bbuf_rem_data) { + /* instead of -1 it should be -amount but RXDRDY event is not generated + * for bytes following first that goes to FIFO they are generated during flushing. + */ + dst = &cfg->bounce_buf[cbwt_data->bounce_idx][cbwt_data->bounce_off + rem_data - 1]; + } else { + /* See comment in if clause. */ + dst = &cbwt_data->curr_bounce_buf[rem_data - bbuf_rem_data - 1]; + } + + if (IS_ENABLED(UARTE_ANY_CACHE) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_invd_range(cfg->rx_flush_buf, amount); + sys_cache_data_invd_range(dst, amount); + } + + memcpy(dst, cfg->rx_flush_buf, amount); +} + +static void cbwt_rxto_isr(const struct device *dev, bool do_flush) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + if (async_rx->buf) { + notify_new_data(dev, false); + } + + if (async_rx->buf) { + rx_buf_release(dev, async_rx->buf); + async_rx->buf = NULL; + } + + if (async_rx->next_buf) { + rx_buf_release(dev, async_rx->next_buf); + async_rx->next_buf = NULL; + } + + if (do_flush) { + cbwt_rx_flush_handle(dev); + } + + if (async_rx->discard_fifo) { + cbwt_data->discard_fifo = async_rx->discard_fifo; + async_rx->discard_fifo = false; + } + nrf_timer_task_trigger(cfg->timer_regs, NRF_TIMER_TASK_STOP); + rx_disable_finalize(dev); +} + +static bool timer_ch_evt_check_clear(NRF_TIMER_Type *timer, uint32_t ch) { - struct uarte_nrfx_data *data = dev->data; - bool already_active = (data->flags & UARTE_FLAG_LOW_POWER) != 0; + nrf_timer_event_t evt = nrf_timer_compare_event_get(ch); - data->flags |= act_mask; - if (already_active) { - /* Second direction already enabled so UARTE is enabled. */ - return; + if (nrf_timer_event_check(timer, evt)) { + nrf_timer_event_clear(timer, evt); + return true; } - uarte_periph_enable(dev); + return false; } -/* At this point we should have irq locked and any previous transfer completed. - * Transfer can be started, no need to wait for completion. - */ -static void tx_start(const struct device *dev, const uint8_t *buf, size_t len) +static void timer_isr(const void *arg) { - const struct uarte_nrfx_config *config = dev->config; - NRF_UARTE_Type *uarte = get_uarte_instance(dev); + const struct device *dev = arg; + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + static const uint32_t flags_to_check = UARTE_FLAG_RX_BUF_REQ | + UARTE_FLAG_TRIG_RXTO | + UARTE_FLAG_LATE_CC; + uint32_t flags = atomic_and(&data->flags, ~flags_to_check); -#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME) - enum pm_device_state state; + cbwt_data->in_irq = true; - (void)pm_device_state_get(dev, &state); - if (state != PM_DEVICE_STATE_ACTIVE) { - return; + if (timer_ch_evt_check_clear(cfg->timer_regs, UARTE_TIMER_USR_CNT_CH) || + (flags & UARTE_FLAG_LATE_CC)) { + usr_buf_complete(dev); } -#endif - if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { - sys_cache_data_flush_range((void *)buf, len); + /* Must be after user buf complet CC handling. */ + if (timer_ch_evt_check_clear(cfg->timer_regs, UARTE_TIMER_BUF_SWITCH_CH)) { + bounce_buf_switch(dev); } - nrf_uarte_tx_buffer_set(uarte, buf, len); - if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT)) { - nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX); + if (flags & UARTE_FLAG_RX_BUF_REQ) { + rx_buf_req(dev); } - nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED); - if (LOW_POWER_ENABLED(config)) { - uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_TX); + if (flags & UARTE_FLAG_TRIG_RXTO) { + cbwt_rxto_isr(dev, false); } - nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX); -} - -#if defined(UARTE_ANY_ASYNC) -static void rx_timeout(struct k_timer *timer); -static void tx_timeout(struct k_timer *timer); -#if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) -static void timer_handler(nrf_timer_event_t event_type, void *p_context) { } + cbwt_data->in_irq = false; +} -static int uarte_nrfx_rx_counting_init(const struct device *dev) +static void cbwt_rx_enable(const struct device *dev, bool with_timeout) { - struct uarte_nrfx_data *data = dev->data; const struct uarte_nrfx_config *cfg = dev->config; - NRF_UARTE_Type *uarte = get_uarte_instance(dev); - int ret; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t rem_data; + uint32_t len = async_rx->buf_len; + uint32_t rx_int_mask = NRF_UARTE_INT_RXTO_MASK | + (with_timeout ? NRF_UARTE_INT_RXDRDY_MASK : 0); + + if (cbwt_data->discard_fifo) { + rem_data = 0; + cbwt_data->discard_fifo = false; + } else { + rem_data = get_byte_cnt(cfg->timer_regs) - cbwt_data->last_cnt; + } - if (HW_RX_COUNTING_ENABLED(cfg)) { - nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG( - NRF_TIMER_BASE_FREQUENCY_GET(cfg->timer.p_reg)); - uint32_t evt_addr = nrf_uarte_event_address_get(uarte, NRF_UARTE_EVENT_RXDRDY); - uint32_t tsk_addr = nrfx_timer_task_address_get(&cfg->timer, NRF_TIMER_TASK_COUNT); + cbwt_data->usr_rd_off = 0; + cbwt_data->usr_wr_off = 0; - tmr_config.mode = NRF_TIMER_MODE_COUNTER; - tmr_config.bit_width = NRF_TIMER_BIT_WIDTH_32; - ret = nrfx_timer_init(&cfg->timer, - &tmr_config, - timer_handler); - if (ret != NRFX_SUCCESS) { - LOG_ERR("Timer already initialized"); - return -EINVAL; - } else { - nrfx_timer_clear(&cfg->timer); - } + if (rem_data >= len) { + atomic_or(&data->flags, UARTE_FLAG_TRIG_RXTO); + NRFX_IRQ_PENDING_SET(cfg->timer_irqn); + return; + } else if (rem_data) { + (void)update_usr_buf(dev, rem_data, false, true); + len -= rem_data; + } + + prepare_bounce_buf(dev, cfg->bounce_buf[0], get_swap_len(dev), cfg->bounce_buf_len); + + cbwt_data->last_cnt = 0; + cbwt_data->bounce_off = 0; + cbwt_data->bounce_idx = 0; + cbwt_data->curr_bounce_buf = cfg->bounce_buf[0]; + cbwt_data->bounce_limit = cfg->bounce_buf_len; + /* Enable ArrayList. */ + nrf_uarte_shorts_enable(cfg->uarte_regs, NRF_UARTE_SHORT_ENDRX_STARTRX); + nrf_uarte_event_clear(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY); + nrf_uarte_int_enable(cfg->uarte_regs, rx_int_mask); + nrf_uarte_rx_buffer_set(cfg->uarte_regs, cbwt_data->curr_bounce_buf, 1); + + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_BUF_SWITCH_CH)); + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_USR_CNT_CH)); + nrf_timer_int_enable(cfg->timer_regs, + nrf_timer_compare_int_get(UARTE_TIMER_BUF_SWITCH_CH) | + nrf_timer_compare_int_get(UARTE_TIMER_USR_CNT_CH)); + nrf_timer_task_trigger(cfg->timer_regs, NRF_TIMER_TASK_CLEAR); + nrf_timer_task_trigger(cfg->timer_regs, NRF_TIMER_TASK_START); + cbwt_data->cc_usr = len; + cbwt_data->cc_swap = get_swap_len(dev); + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_BUF_SWITCH_CH, get_swap_len(dev)); + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_USR_CNT_CH, len); + + atomic_or(&data->flags, UARTE_FLAG_RX_BUF_REQ); + nrf_uarte_task_trigger(cfg->uarte_regs, NRF_UARTE_TASK_STARTRX); + NRFX_IRQ_PENDING_SET(cfg->timer_irqn); +} + +static int cbwt_uarte_async_init(const struct device *dev) +{ + /* As this approach does not use nrfx_timer driver but only HAL special setup + * function is used. + */ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + static const uint32_t rx_int_mask = NRF_UARTE_INT_ERROR_MASK | + NRF_UARTE_INT_RXTO_MASK; + uint32_t evt = nrf_uarte_event_address_get(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY); + uint32_t tsk = nrf_timer_task_address_get(cfg->timer_regs, NRF_TIMER_TASK_COUNT); + nrfx_err_t ret; - ret = nrfx_gppi_channel_alloc(&data->async->rx.cnt.ppi); - if (ret != NRFX_SUCCESS) { - LOG_ERR("Failed to allocate PPI Channel"); - nrfx_timer_uninit(&cfg->timer); - return -EINVAL; - } + nrf_timer_mode_set(cfg->timer_regs, NRF_TIMER_MODE_COUNTER); + nrf_timer_bit_width_set(cfg->timer_regs, NRF_TIMER_BIT_WIDTH_32); - nrfx_gppi_channel_endpoints_setup(data->async->rx.cnt.ppi, evt_addr, tsk_addr); - nrfx_gppi_channels_enable(BIT(data->async->rx.cnt.ppi)); - } else { - nrf_uarte_int_enable(uarte, NRF_UARTE_INT_RXDRDY_MASK); + ret = nrfx_gppi_channel_alloc(&cbwt_data->ppi_ch); + if (ret != NRFX_SUCCESS) { + return -ENOMEM; } + nrfx_gppi_channel_endpoints_setup(cbwt_data->ppi_ch, evt, tsk); + nrfx_gppi_channels_enable(BIT(cbwt_data->ppi_ch)); + +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + cbwt_data->bounce_buf_swap_len = cfg->bounce_buf_swap_len; +#endif + + /* Enable EasyDMA LIST feature (it is exposed in SPIM but not in UARTE). */ + *(volatile uint32_t *)((uint32_t)cfg->uarte_regs + 0x714) = 1; + nrf_uarte_int_enable(cfg->uarte_regs, rx_int_mask); + return 0; } -#endif /* !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) */ +#endif /* CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER */ static int uarte_async_init(const struct device *dev) { @@ -927,6 +1646,17 @@ static int uarte_async_init(const struct device *dev) ((IS_ENABLED(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) && !IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT)) ? NRF_UARTE_INT_RXDRDY_MASK : 0); + k_timer_init(&data->async->rx.timer, rx_timeout, NULL); + k_timer_user_data_set(&data->async->rx.timer, (void *)dev); + k_timer_init(&data->async->tx.timer, tx_timeout, NULL); + k_timer_user_data_set(&data->async->tx.timer, (void *)dev); + +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev)) { + return cbwt_uarte_async_init(dev); + } +#endif + #if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) int ret = uarte_nrfx_rx_counting_init(dev); @@ -937,11 +1667,6 @@ static int uarte_async_init(const struct device *dev) nrf_uarte_int_enable(uarte, rx_int_mask); - k_timer_init(&data->async->rx.timer, rx_timeout, NULL); - k_timer_user_data_set(&data->async->rx.timer, (void *)dev); - k_timer_init(&data->async->tx.timer, tx_timeout, NULL); - k_timer_user_data_set(&data->async->tx.timer, (void *)dev); - return 0; } @@ -1025,20 +1750,6 @@ static int uarte_nrfx_tx(const struct device *dev, const uint8_t *buf, } if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - if (!IS_PM_ISR_SAFE(dev) && k_is_in_isr()) { - /* If instance does not support PM from ISR device shall - * already be turned on. - */ - enum pm_device_state state; - int err; - - err = pm_device_state_get(dev, &state); - (void)err; - __ASSERT_NO_MSG(err == 0); - if (state != PM_DEVICE_STATE_ACTIVE) { - return -ENOTSUP; - } - } pm_device_runtime_get(dev); } @@ -1068,15 +1779,6 @@ static int uarte_nrfx_tx_abort(const struct device *dev) return 0; } -static void user_callback(const struct device *dev, struct uart_event *evt) -{ - struct uarte_nrfx_data *data = dev->data; - - if (data->async->user_callback) { - data->async->user_callback(dev, evt, data->async->user_data); - } -} - static void notify_uart_rx_rdy(const struct device *dev, size_t len) { struct uarte_nrfx_data *data = dev->data; @@ -1090,29 +1792,6 @@ static void notify_uart_rx_rdy(const struct device *dev, size_t len) user_callback(dev, &evt); } -static void rx_buf_release(const struct device *dev, uint8_t *buf) -{ - struct uart_event evt = { - .type = UART_RX_BUF_RELEASED, - .data.rx_buf.buf = buf, - }; - - user_callback(dev, &evt); -} - -static void notify_rx_disable(const struct device *dev) -{ - struct uart_event evt = { - .type = UART_RX_DISABLED, - }; - - user_callback(dev, (struct uart_event *)&evt); - - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put_async(dev, K_NO_WAIT); - } -} - #ifdef UARTE_HAS_FRAME_TIMEOUT static uint32_t us_to_bauds(uint32_t baudrate, int32_t timeout) { @@ -1122,6 +1801,7 @@ static uint32_t us_to_bauds(uint32_t baudrate, int32_t timeout) } #endif + static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, size_t len, int32_t timeout) @@ -1131,6 +1811,11 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, const struct uarte_nrfx_config *cfg = dev->config; NRF_UARTE_Type *uarte = get_uarte_instance(dev); +#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) || \ + defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) + bool with_timeout = timeout != SYS_FOREVER_US; +#endif + if (cfg->disable_rx) { __ASSERT(false, "TX only UARTE instance"); return -ENOTSUP; @@ -1145,35 +1830,45 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, } #ifdef CONFIG_HAS_NORDIC_DMM - uint8_t *dma_buf; - int ret = 0; + if (!IS_CBWT(dev)) { + void *dma_buf; + int ret = 0; - ret = dmm_buffer_in_prepare(cfg->mem_reg, buf, len, (void **)&dma_buf); - if (ret < 0) { - return ret; - } + ret = dmm_buffer_in_prepare(cfg->mem_reg, buf, len, &dma_buf); + if (ret < 0) { + return ret; + } - async_rx->usr_buf = buf; - buf = dma_buf; + async_rx->usr_buf = buf; + buf = dma_buf; + } #endif -#ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX +#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) || \ + defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) + #ifdef UARTE_HAS_FRAME_TIMEOUT - if (timeout != SYS_FOREVER_US) { + if (!IS_CBWT(dev) && with_timeout) { uint32_t baudrate = COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, - (data->uart_config.baudrate), (cfg->baudrate)); - - async_rx->timeout = K_USEC(timeout); + (data->uart_config.baudrate), (cfg->baudrate)); nrf_uarte_frame_timeout_set(uarte, us_to_bauds(baudrate, timeout)); nrf_uarte_shorts_enable(uarte, NRF_UARTE_SHORT_FRAME_TIMEOUT_STOPRX); + } +#endif +#if !defined(UARTE_HAS_FRAME_TIMEOUT) || defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) + async_rx->idle_cnt = 0; +#endif + + if (with_timeout) { + if (!IS_CBWT(dev) && IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT)) { + async_rx->timeout = K_USEC(timeout); + } else { + async_rx->timeout = with_timeout ? + K_USEC(timeout / RX_TIMEOUT_DIV) : K_NO_WAIT; + } } else { async_rx->timeout = K_NO_WAIT; } -#else - async_rx->timeout = (timeout == SYS_FOREVER_US) ? - K_NO_WAIT : K_USEC(timeout / RX_TIMEOUT_DIV); - async_rx->idle_cnt = 0; -#endif /* UARTE_HAS_FRAME_TIMEOUT */ #else async_rx->timeout_us = timeout; async_rx->timeout_slab = timeout / RX_TIMEOUT_DIV; @@ -1186,22 +1881,20 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, async_rx->next_buf_len = 0; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - if (!IS_PM_ISR_SAFE(dev) && k_is_in_isr()) { - /* If instance does not support PM from ISR device shall - * already be turned on. - */ - enum pm_device_state state; - int err; - - err = pm_device_state_get(dev, &state); - (void)err; - __ASSERT_NO_MSG(err == 0); - if (state != PM_DEVICE_STATE_ACTIVE) { - return -ENOTSUP; - } - } pm_device_runtime_get(dev); + } else if (LOW_POWER_ENABLED(cfg)) { + unsigned int key = irq_lock(); + + uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_RX); + irq_unlock(key); + } + +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev)) { + cbwt_rx_enable(dev, with_timeout); + return 0; } +#endif if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || LOW_POWER_ENABLED(cfg)) { if (async_rx->flush_cnt) { @@ -1239,7 +1932,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, return 0; } else { #ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX - if (!K_TIMEOUT_EQ(async_rx->timeout, K_NO_WAIT)) { + if (with_timeout) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXDRDY); k_timer_start(&async_rx->timer, async_rx->timeout, K_NO_WAIT); @@ -1251,7 +1944,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, nrf_uarte_rx_buffer_set(uarte, buf, len); - if (IS_ENABLED(UARTE_ANY_FAST) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + if (IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE120) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { /* Spurious RXTO event was seen on fast instance (UARTE120) thus * RXTO interrupt is kept enabled only when RX is active. */ @@ -1264,13 +1957,6 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, async_rx->enabled = true; - if (LOW_POWER_ENABLED(cfg)) { - unsigned int key = irq_lock(); - - uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_RX); - irq_unlock(key); - } - nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTRX); return 0; @@ -1289,29 +1975,33 @@ static int uarte_nrfx_rx_buf_rsp(const struct device *dev, uint8_t *buf, err = -EACCES; } else if (async_rx->next_buf == NULL) { #ifdef CONFIG_HAS_NORDIC_DMM - uint8_t *dma_buf; - const struct uarte_nrfx_config *config = dev->config; + if (!IS_CBWT(dev)) { + uint8_t *dma_buf; + const struct uarte_nrfx_config *config = dev->config; - err = dmm_buffer_in_prepare(config->mem_reg, buf, len, (void **)&dma_buf); - if (err < 0) { - return err; + err = dmm_buffer_in_prepare(config->mem_reg, buf, len, (void **)&dma_buf); + if (err < 0) { + return err; + } + async_rx->next_usr_buf = buf; + buf = dma_buf; } - async_rx->next_usr_buf = buf; - buf = dma_buf; #endif async_rx->next_buf = buf; async_rx->next_buf_len = len; - nrf_uarte_rx_buffer_set(uarte, buf, len); - /* If buffer is shorter than RX FIFO then there is a risk that due - * to interrupt handling latency ENDRX event is not handled on time - * and due to ENDRX_STARTRX short data will start to be overwritten. - * In that case short is not enabled and ENDRX event handler will - * manually start RX for that buffer. Thanks to RX FIFO there is - * 5 byte time for doing that. If interrupt latency is higher and - * there is no HWFC in both cases data will be lost or corrupted. - */ - if (len >= UARTE_HW_RX_FIFO_SIZE) { - nrf_uarte_shorts_enable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); + if (!IS_CBWT(dev)) { + nrf_uarte_rx_buffer_set(uarte, buf, len); + /* If buffer is shorter than RX FIFO then there is a risk that due + * to interrupt handling latency ENDRX event is not handled on time + * and due to ENDRX_STARTRX short data will start to be overwritten. + * In that case short is not enabled and ENDRX event handler will + * manually start RX for that buffer. Thanks to RX FIFO there is + * 5 byte time for doing that. If interrupt latency is higher and + * there is no HWFC in both cases data will be lost or corrupted. + */ + if (len >= UARTE_HW_RX_FIFO_SIZE) { + nrf_uarte_shorts_enable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); + } } err = 0; } else { @@ -1339,35 +2029,6 @@ static int uarte_nrfx_callback_set(const struct device *dev, return 0; } -static int uarte_nrfx_rx_disable(const struct device *dev) -{ - struct uarte_nrfx_data *data = dev->data; - struct uarte_async_rx *async_rx = &data->async->rx; - NRF_UARTE_Type *uarte = get_uarte_instance(dev); - int key; - - if (async_rx->buf == NULL) { - return -EFAULT; - } - - k_timer_stop(&async_rx->timer); - - key = irq_lock(); - - if (async_rx->next_buf != NULL) { - nrf_uarte_shorts_disable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); - nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); - } - - async_rx->enabled = false; - async_rx->discard_fifo = true; - - nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX); - irq_unlock(key); - - return 0; -} - static void tx_timeout(struct k_timer *timer) { const struct device *dev = k_timer_user_data_get(timer); @@ -1390,6 +2051,13 @@ static void rx_timeout(struct k_timer *timer) NRF_UARTE_Type *uarte = get_uarte_instance(dev); #ifdef UARTE_HAS_FRAME_TIMEOUT +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev)) { + cbwt_rx_timeout(timer); + return; + } +#endif + struct uarte_nrfx_data *data = dev->data; struct uarte_async_rx *async_rx = &data->async->rx; bool rxdrdy = nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXDRDY); @@ -1536,7 +2204,7 @@ static void error_isr(const struct device *dev) nrf_uarte_errorsrc_clear(uarte, err); user_callback(dev, &evt); - (void) uarte_nrfx_rx_disable(dev); + (void)rx_disable(dev, false); } static void rxstarted_isr(const struct device *dev) @@ -1755,7 +2423,6 @@ static void rxto_isr(const struct device *dev) * In the second case, additionally, data from the UARTE internal RX * FIFO need to be discarded. */ - async_rx->enabled = false; if (async_rx->discard_fifo) { async_rx->discard_fifo = false; #if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) @@ -1772,7 +2439,7 @@ static void rxto_isr(const struct device *dev) #ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX NRF_UARTE_Type *uarte = get_uarte_instance(dev); - if (IS_ENABLED(UARTE_ANY_FAST) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { + if (IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE120) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { /* Spurious RXTO event was seen on fast instance (UARTE120) thus * RXTO interrupt is kept enabled only when RX is active. */ @@ -1783,15 +2450,7 @@ static void rxto_isr(const struct device *dev) #endif nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXDRDY); #endif - - if (LOW_POWER_ENABLED(config)) { - uint32_t key = irq_lock(); - - uarte_disable_locked(dev, UARTE_FLAG_LOW_POWER_RX); - irq_unlock(key); - } - - notify_rx_disable(dev); + rx_disable_finalize(dev); } static void txstopped_isr(const struct device *dev) @@ -1881,10 +2540,12 @@ static void txstopped_isr(const struct device *dev) static void rxdrdy_isr(const struct device *dev) { -#if !defined(UARTE_HAS_FRAME_TIMEOUT) +#if !defined(UARTE_HAS_FRAME_TIMEOUT) || defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) struct uarte_nrfx_data *data = dev->data; -#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) +#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) || \ + defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) + NRF_UARTE_Type *uarte = get_uarte_instance(dev); data->async->rx.idle_cnt = 0; @@ -1916,8 +2577,9 @@ static void uarte_nrfx_isr_async(const void *arg) struct uarte_async_rx *async_rx = &data->async->rx; uint32_t imask = nrf_uarte_int_enable_check(uarte, UINT32_MAX); - if (!(HW_RX_COUNTING_ENABLED(config) || IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT)) - && event_check_clear(uarte, NRF_UARTE_EVENT_RXDRDY, NRF_UARTE_INT_RXDRDY_MASK, imask)) { + if ((IS_CBWT(dev) || + !(HW_RX_COUNTING_ENABLED(config) || IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT))) && + event_check_clear(uarte, NRF_UARTE_EVENT_RXDRDY, NRF_UARTE_INT_RXDRDY_MASK, imask)) { rxdrdy_isr(dev); } @@ -1945,6 +2607,12 @@ static void uarte_nrfx_isr_async(const void *arg) rxstarted_isr(dev); } +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev) && + event_check_clear(uarte, NRF_UARTE_EVENT_RXTO, NRF_UARTE_INT_RXTO_MASK, imask)) { + cbwt_rxto_isr(dev, true); + } else +#endif /* RXTO must be handled after ENDRX which should notify the buffer. * Skip if ENDRX is set when RXTO is set. It means that * ENDRX occurred after check for ENDRX in isr which may happen when @@ -1969,7 +2637,8 @@ static void uarte_nrfx_isr_async(const void *arg) txstopped_isr(dev); } - if (atomic_and(&data->flags, ~UARTE_FLAG_TRIG_RXTO) & UARTE_FLAG_TRIG_RXTO) { + if (!IS_CBWT(dev) && + (atomic_and(&data->flags, ~UARTE_FLAG_TRIG_RXTO) & UARTE_FLAG_TRIG_RXTO)) { #ifdef CONFIG_HAS_NORDIC_DMM int ret; @@ -1984,7 +2653,7 @@ static void uarte_nrfx_isr_async(const void *arg) rx_buf_release(dev, async_rx->buf); async_rx->buf_len = 0; async_rx->buf = NULL; - notify_rx_disable(dev); + rx_disable_finalize(dev); } } @@ -2063,22 +2732,6 @@ static void uarte_nrfx_poll_out(const struct device *dev, unsigned char c) } if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - if (!IS_PM_ISR_SAFE(dev) && k_is_in_isr()) { - /* If instance does not support PM from ISR device shall - * already be turned on. - */ - enum pm_device_state state; - int err; - - err = pm_device_state_get(dev, &state); - (void)err; - __ASSERT_NO_MSG(err == 0); - if (state != PM_DEVICE_STATE_ACTIVE) { - irq_unlock(key); - return; - } - } - if (!(data->flags & UARTE_FLAG_POLL_OUT)) { data->flags |= UARTE_FLAG_POLL_OUT; pm_device_runtime_get(dev); @@ -2404,15 +3057,6 @@ static void uarte_pm_suspend(const struct device *dev) struct uarte_nrfx_data *data = dev->data; (void)data; -#ifdef UARTE_ANY_FAST - if (cfg->clk_dev) { - int err; - - err = nrf_clock_control_release(cfg->clk_dev, &cfg->clk_spec); - (void)err; - __ASSERT_NO_MSG(err >= 0); - } -#endif #ifdef UARTE_ANY_ASYNC if (data->async) { @@ -2466,20 +3110,6 @@ static void uarte_pm_suspend(const struct device *dev) wait_for_tx_stopped(dev); } -#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED - if (cfg->cross_domain && uarte_has_cross_domain_connection(cfg)) { -#if UARTE_CROSS_DOMAIN_PINS_HANDLE - int err; - - err = nrf_sys_event_release_global_constlat(); - (void)err; - __ASSERT_NO_MSG(err >= 0); -#else - __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); -#endif - } -#endif - (void)pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_SLEEP); nrf_uarte_disable(uarte); } @@ -2598,6 +3228,44 @@ static int uarte_instance_deinit(const struct device *dev) return pm_device_driver_deinit(dev, uarte_nrfx_pm_action); } +#define UARTE_TIMER_REG(idx) (NRF_TIMER_Type *)DT_REG_ADDR(DT_PHANDLE(UARTE(idx), timer)) + +#define UARTE_TIMER_IRQN(idx) DT_IRQN(DT_PHANDLE(UARTE(idx), timer)) + +#define UARTE_TIMER_IRQ_PRIO(idx) DT_IRQ(DT_PHANDLE(UARTE(idx), timer), priority) + +#define UARTE_COUNT_BYTES_WITH_TIMER_CONFIG(idx) \ + IF_ENABLED(UARTE_HAS_PROP(idx, timer), \ + (.timer_regs = UARTE_TIMER_REG(idx), \ + .timer_irqn = UARTE_TIMER_IRQN(idx), \ + .uarte_irqn = DT_IRQN(UARTE(idx)), \ + .bounce_buf = { \ + uart##idx##_bounce_buf, \ + &uart##idx##_bounce_buf[sizeof(uart##idx##_bounce_buf) / 2] \ + }, \ + .bounce_buf_len = sizeof(uart##idx##_bounce_buf) / 2, \ + .bounce_buf_swap_len = UARTE_BUF_SWAP_LEN(sizeof(uart##idx##_bounce_buf) / 2,\ + UARTE_US_TO_BYTES(UARTE_PROP(idx, current_speed))), \ + .cbwt_data = &uart##idx##_bounce_data,)) + +#define UARTE_COUNT_BYTES_WITH_TIMER_VALIDATE_CONFIG(idx) \ + __ASSERT_NO_MSG(UARTE_TIMER_IRQ_PRIO(idx) == DT_IRQ(UARTE(idx), priority)) + +#define UARTE_TIMER_IRQ_CONNECT(idx, func) \ + IF_ENABLED(UTIL_AND(IS_ENABLED(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER), \ + UARTE_HAS_PROP(idx, timer)), \ + (UARTE_COUNT_BYTES_WITH_TIMER_VALIDATE_CONFIG(idx); \ + IRQ_CONNECT(UARTE_TIMER_IRQN(idx), UARTE_TIMER_IRQ_PRIO(idx), func, \ + DEVICE_DT_GET(UARTE(idx)), 0); \ + irq_enable(UARTE_TIMER_IRQN(idx));)) + +/* Macro sets flag to indicate that uart use different interrupt priority than the system clock. */ +#define UARTE_HAS_VAR_PRIO(idx) \ + COND_CODE_1(UTIL_AND(IS_ENABLED(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER), \ + UARTE_HAS_PROP(idx, timer)), \ + ((DT_IRQ(UARTE(idx), priority) != DT_IRQ(DT_NODELABEL(grtc), priority)) ? \ + UARTE_CFG_FLAG_VAR_IRQ : 0), (0)) + #define UARTE_GET_ISR(idx) \ COND_CODE_1(CONFIG_UART_##idx##_ASYNC, (uarte_nrfx_isr_async), (uarte_nrfx_isr_int)) @@ -2613,16 +3281,18 @@ static int uarte_instance_deinit(const struct device *dev) )) /* Depending on configuration standard or direct IRQ is connected. */ -#define UARTE_IRQ_CONNECT(idx, irqn, prio) \ - COND_CODE_1(CONFIG_UART_NRFX_UARTE_NO_IRQ, (), \ - (COND_CODE_1(CONFIG_UART_NRFX_UARTE_DIRECT_ISR, \ - (IRQ_DIRECT_CONNECT(irqn, prio, uarte_##idx##_direct_isr, 0)), \ - (IRQ_CONNECT(irqn, prio, UARTE_GET_ISR(idx), DEVICE_DT_GET(UARTE(idx)), 0))))) +#define UARTE_IRQ_CONNECT(idx, irqn, prio) \ + COND_CODE_1(CONFIG_UART_NRFX_UARTE_NO_IRQ, (), \ + (COND_CODE_1(CONFIG_UART_NRFX_UARTE_DIRECT_ISR, \ + (IRQ_DIRECT_CONNECT(irqn, prio, uarte_##idx##_direct_isr, 0)), \ + (IRQ_CONNECT(irqn, prio, UARTE_GET_ISR(idx), \ + DEVICE_DT_GET(UARTE(idx)), 0))))) #define UARTE_IRQ_CONFIGURE(idx) \ do { \ UARTE_IRQ_CONNECT(idx, DT_IRQN(UARTE(idx)), DT_IRQ(UARTE(idx), priority)); \ irq_enable(DT_IRQN(UARTE(idx))); \ + UARTE_TIMER_IRQ_CONNECT(idx, timer_isr) \ } while (false) /* Low power mode is used when disable_rx is not defined or in async mode if @@ -2654,20 +3324,6 @@ static int uarte_instance_deinit(const struct device *dev) #define UARTE_GET_BAUDRATE(idx) \ UARTE_GET_BAUDRATE2(NRF_PERIPH_GET_FREQUENCY(UARTE(idx)), UARTE_PROP(idx, current_speed)) -/* Get initialization level of an instance. Instances that requires clock control - * which is using nrfs (IPC) are initialized later. - */ -#define UARTE_INIT_LEVEL(idx) \ - COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _), (POST_KERNEL), (PRE_KERNEL_1)) - -/* Get initialization priority of an instance. Instances that requires clock control - * which is using nrfs (IPC) are initialized later. - */ -#define UARTE_INIT_PRIO(idx) \ - COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \ - (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \ - (CONFIG_SERIAL_INIT_PRIORITY)) - /* Macro for setting nRF specific configuration structures. */ #define UARTE_NRF_CONFIG(idx) { \ .hwfc = (UARTE_PROP(idx, hw_flow_control) == \ @@ -2695,33 +3351,24 @@ static int uarte_instance_deinit(const struct device *dev) : UART_CFG_FLOW_CTRL_NONE, \ } -#define UARTE_ON_MANAGED_POWER_DOMAIN(idx) \ - UTIL_AND( \ - IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN), \ - UTIL_AND( \ - DT_NODE_HAS_PROP(UARTE(idx), power_domains), \ - DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE(UARTE(idx), power_domains)) \ - ) \ - ) - /* Macro determines if PM actions are interrupt safe. * - * Requesting/releasing clocks or power domains is not necessarily ISR safe (we can't - * reliably know, its out of our control). UARTE_ON_MANAGED_POWER_DOMAIN() let's us check if we - * will be requesting/releasing power domains (and clocks for now since the only case where we - * need to request power domains happens to be the same criteria). - * - * Furthermore, non-asynchronous API if RX is disabled is not ISR safe. + * Non-asynchronous API if RX is disabled is not ISR safe. * * Macro must resolve to a literal 1 or 0. */ #define UARTE_PM_ISR_SAFE(idx) \ - COND_CODE_1(UARTE_ON_MANAGED_POWER_DOMAIN(idx), \ - (0), \ - (COND_CODE_1(CONFIG_UART_##idx##_ASYNC, \ - (PM_DEVICE_ISR_SAFE), \ - (COND_CODE_1(UARTE_PROP(idx, disable_rx), \ - (PM_DEVICE_ISR_SAFE), (0)))))) \ + COND_CODE_1( \ + CONFIG_UART_##idx##_ASYNC, \ + (PM_DEVICE_ISR_SAFE), \ + ( \ + COND_CODE_1( \ + UARTE_PROP(idx, disable_rx), \ + (PM_DEVICE_ISR_SAFE), \ + (0) \ + ) \ + ) \ + ) #define UART_NRF_UARTE_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(UARTE(idx)); \ @@ -2729,6 +3376,12 @@ static int uarte_instance_deinit(const struct device *dev) UARTE_INT_DRIVEN(idx); \ PINCTRL_DT_DEFINE(UARTE(idx)); \ IF_ENABLED(CONFIG_UART_##idx##_ASYNC, ( \ + IF_ENABLED(UTIL_AND(IS_ENABLED(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER), \ + UARTE_HAS_PROP(idx, timer)), \ + (static uint8_t uart##idx##_bounce_buf[CONFIG_UART_NRFX_UARTE_BOUNCE_BUF_LEN] \ + DMM_MEMORY_SECTION(UARTE(idx)); \ + static struct uarte_async_rx_cbwt uart##idx##_bounce_data; \ + )) \ static uint8_t \ uarte##idx##_tx_cache[CONFIG_UART_ASYNC_TX_CACHE_SIZE] \ DMM_MEMORY_SECTION(UARTE(idx)); \ @@ -2770,6 +3423,10 @@ static int uarte_instance_deinit(const struct device *dev) (IS_ENABLED(CONFIG_UART_NRFX_UARTE_SPURIOUS_RXTO_WORKAROUND) && \ INSTANCE_IS_HIGH_SPEED(_, /*empty*/, idx, _) ? \ UARTE_CFG_FLAG_SPURIOUS_RXTO : 0) | \ + ((IS_ENABLED(UARTE_BAUDRATE_RETENTION_WORKAROUND) && \ + UARTE_IS_CACHEABLE(idx)) ? \ + UARTE_CFG_FLAG_VOLATILE_BAUDRATE : 0) | \ + UARTE_HAS_VAR_PRIO(idx) | \ USE_LOW_POWER(idx), \ UARTE_DISABLE_RX_INIT(UARTE(idx)), \ .poll_out_byte = &uarte##idx##_poll_out_byte, \ @@ -2777,21 +3434,11 @@ static int uarte_instance_deinit(const struct device *dev) IF_ENABLED(CONFIG_UART_##idx##_ASYNC, \ (.tx_cache = uarte##idx##_tx_cache, \ .rx_flush_buf = uarte##idx##_flush_buf,)) \ + IF_ENABLED(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER, \ + (UARTE_COUNT_BYTES_WITH_TIMER_CONFIG(idx))) \ IF_ENABLED(CONFIG_UART_##idx##_NRF_HW_ASYNC, \ (.timer = NRFX_TIMER_INSTANCE( \ CONFIG_UART_##idx##_NRF_HW_ASYNC_TIMER),)) \ - IF_ENABLED(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \ - (.clk_dev = DEVICE_DT_GET_OR_NULL(DT_CLOCKS_CTLR(UARTE(idx))), \ - .clk_spec = { \ - .frequency = NRF_PERIPH_GET_FREQUENCY(UARTE(idx)),\ - .accuracy = 0, \ - .precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,\ - },)) \ - IF_ENABLED(UARTE_PINS_CROSS_DOMAIN(_, /*empty*/, idx, _), \ - (.cross_domain = true, \ - .default_port = \ - DT_PROP_OR(DT_PHANDLE(UARTE(idx), \ - default_gpio_port), port, -1),)) \ }; \ UARTE_DIRECT_ISR_DECLARE(idx) \ static int uarte_##idx##_init(const struct device *dev) \ @@ -2811,8 +3458,8 @@ static int uarte_instance_deinit(const struct device *dev) PM_DEVICE_DT_GET(UARTE(idx)), \ &uarte_##idx##_data, \ &uarte_##idx##z_config, \ - UARTE_INIT_LEVEL(idx), \ - UARTE_INIT_PRIO(idx), \ + PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, \ &uart_nrfx_uarte_driver_api) #define UARTE_INT_DRIVEN(idx) \ @@ -2829,5 +3476,4 @@ static int uarte_instance_deinit(const struct device *dev) #define COND_UART_NRF_UARTE_DEVICE(unused, prefix, i, _) \ IF_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i, (UART_NRF_UARTE_DEVICE(prefix##i);)) - UARTE_FOR_EACH_INSTANCE(COND_UART_NRF_UARTE_DEVICE, (), ()) diff --git a/drivers/spi/spi_dw.c b/drivers/spi/spi_dw.c index bd10447e4429..6941bfdaaa77 100644 --- a/drivers/spi/spi_dw.c +++ b/drivers/spi/spi_dw.c @@ -41,6 +41,14 @@ LOG_MODULE_REGISTER(spi_dw); #include #endif +#ifdef CONFIG_HAS_NRFX +#include +#endif + +#ifdef CONFIG_SOC_NRF54H20_GPD +#include +#endif + static inline bool spi_dw_is_slave(struct spi_dw_data *spi) { return (IS_ENABLED(CONFIG_SPI_SLAVE) && @@ -258,6 +266,7 @@ static int spi_dw_configure(const struct device *dev, /* Baud rate and Slave select, for master only */ write_baudr(dev, SPI_DW_CLK_DIVIDER(info->clock_frequency, config->frequency)); + write_ser(dev, BIT(config->slave)); } if (spi_dw_is_slave(spi)) { @@ -512,6 +521,10 @@ void spi_dw_isr(const struct device *dev) uint32_t int_status; int error; +#ifdef CONFIG_HAS_NRFX + NRF_EXMIF->EVENTS_CORE = 0; +#endif + int_status = read_isr(dev); LOG_DBG("SPI %p int_status 0x%x - (tx: %d, rx: %d)", dev, int_status, @@ -560,6 +573,18 @@ int spi_dw_init(const struct device *dev) DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); +#ifdef CONFIG_HAS_NRFX + NRF_EXMIF->INTENSET = BIT(0); + NRF_EXMIF->TASKS_START = 1; + +#ifdef CONFIG_SOC_NRF54H20_GPD + err = nrf_gpd_request(NRF_GPD_FAST_ACTIVE1); + if (err < 0) { + return err; + } +#endif +#endif + info->config_func(); /* Masking interrupt and making sure controller is disabled */ @@ -584,6 +609,11 @@ int spi_dw_init(const struct device *dev) return 0; } +#define REG_ADDR(inst) \ + COND_CODE_1(DT_NODE_HAS_COMPAT(DT_DRV_INST(inst), nordic_nrf_exmif_spi), \ + (Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(core, DT_DRV_INST(inst))), \ + (DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst)))) + #define SPI_CFG_IRQS_SINGLE_ERR_LINE(inst) \ IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, rx_avail, irq), \ DT_INST_IRQ_BY_NAME(inst, rx_avail, priority), \ @@ -656,7 +686,7 @@ COND_CODE_1(IS_EQ(DT_NUM_IRQS(DT_DRV_INST(inst)), 1), \ SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), ctx) \ }; \ static const struct spi_dw_config spi_dw_config_##inst = { \ - DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst)), \ + REG_ADDR(inst), \ .clock_frequency = COND_CODE_1( \ DT_NODE_HAS_PROP(DT_INST_PHANDLE(inst, clocks), clock_frequency), \ (DT_INST_PROP_BY_PHANDLE(inst, clocks, clock_frequency)), \ diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index 447c0e54fba5..390682260c81 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -55,53 +54,6 @@ LOG_MODULE_REGISTER(spi_nrfx_spim, CONFIG_SPI_LOG_LEVEL); #define SPIM_FOR_EACH_INSTANCE(f, sep, off_code, ...) \ NRFX_FOREACH_PRESENT(SPIM, f, sep, off_code, __VA_ARGS__) -/* Only CPUAPP and CPURAD can control clocks and power domains, so if a fast instance is - * used by other cores, treat the SPIM like a normal one. This presumes the CPUAPP or CPURAD - * have requested the clocks and power domains needed by the fast instance to be ACTIVE before - * other cores use the fast instance. - */ -#if CONFIG_SOC_NRF54H20_CPUAPP || CONFIG_SOC_NRF54H20_CPURAD -#define INSTANCE_IS_FAST(unused, prefix, idx, _) \ - UTIL_AND( \ - UTIL_AND( \ - IS_ENABLED(CONFIG_HAS_HW_NRF_SPIM##prefix##idx), \ - NRF_DT_IS_FAST(SPIM(idx)) \ - ), \ - IS_ENABLED(CONFIG_CLOCK_CONTROL) \ - ) - -#if SPIM_FOR_EACH_INSTANCE(INSTANCE_IS_FAST, (||), (0)) -#define SPIM_ANY_FAST 1 -/* If fast instances are used then system managed device PM cannot be used because - * it may call PM actions from locked context and fast SPIM PM actions can only be - * called from a thread context. - */ -BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED)); -#endif -#endif - -#define SPIM_PINS_CROSS_DOMAIN(unused, prefix, idx, _) \ - COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(SPIM(prefix##idx)), \ - (SPIM_PROP(idx, cross_domain_pins_supported)), \ - (0)) - -#if NRFX_FOREACH_PRESENT(SPIM, SPIM_PINS_CROSS_DOMAIN, (||), (0)) -#include -/* Certain SPIM instances support usage of cross domain pins in form of dedicated pins on - * a port different from the default one. - */ -#define SPIM_CROSS_DOMAIN_SUPPORTED 1 -#endif - -#if SPIM_CROSS_DOMAIN_SUPPORTED && defined(CONFIG_NRF_SYS_EVENT) -#include -/* To use cross domain pins, constant latency mode needs to be applied, which is - * handled via nrf_sys_event requests. - */ -#define SPIM_CROSS_DOMAIN_PINS_HANDLE 1 -#endif - - struct spi_nrfx_data { struct spi_context ctx; const struct device *dev; @@ -117,9 +69,6 @@ struct spi_nrfx_data { uint8_t ppi_ch; uint8_t gpiote_ch; #endif -#ifdef SPIM_ANY_FAST - bool clock_requested; -#endif }; struct spi_nrfx_config { @@ -134,90 +83,11 @@ struct spi_nrfx_config { #endif uint32_t wake_pin; nrfx_gpiote_t wake_gpiote; -#ifdef SPIM_ANY_FAST - const struct device *clk_dev; - struct nrf_clock_spec clk_spec; -#endif -#if SPIM_CROSS_DOMAIN_SUPPORTED - bool cross_domain; - int8_t default_port; -#endif void *mem_reg; }; static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context); -static inline int request_clock(const struct device *dev) -{ -#ifdef SPIM_ANY_FAST - struct spi_nrfx_data *dev_data = dev->data; - const struct spi_nrfx_config *dev_config = dev->config; - int error; - - if (!dev_config->clk_dev) { - return 0; - } - - error = nrf_clock_control_request_sync( - dev_config->clk_dev, &dev_config->clk_spec, - K_MSEC(CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE)); - if (error < 0) { - LOG_ERR("Failed to request clock: %d", error); - return error; - } - - dev_data->clock_requested = true; -#else - ARG_UNUSED(dev); -#endif - - return 0; -} - -static inline void release_clock(const struct device *dev) -{ -#ifdef SPIM_ANY_FAST - struct spi_nrfx_data *dev_data = dev->data; - const struct spi_nrfx_config *dev_config = dev->config; - - if (!dev_data->clock_requested) { - return; - } - - dev_data->clock_requested = false; - - nrf_clock_control_release(dev_config->clk_dev, &dev_config->clk_spec); -#else - ARG_UNUSED(dev); -#endif -} - -#if SPIM_CROSS_DOMAIN_SUPPORTED -static bool spim_has_cross_domain_connection(const struct spi_nrfx_config *config) -{ - const struct pinctrl_dev_config *pcfg = config->pcfg; - const struct pinctrl_state *state; - int ret; - - ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state); - if (ret < 0) { - LOG_ERR("Unable to read pin state"); - return false; - } - - for (uint8_t i = 0U; i < state->pin_cnt; i++) { - uint32_t pin = NRF_GET_PIN(state->pins[i]); - - if ((pin != NRF_PIN_DISCONNECTED) && - (nrf_gpio_pin_port_number_extract(&pin) != config->default_port)) { - return true; - } - } - - return false; -} -#endif - static inline void finalize_spi_transaction(const struct device *dev, bool deactivate_cs) { struct spi_nrfx_data *dev_data = dev->data; @@ -232,10 +102,6 @@ static inline void finalize_spi_transaction(const struct device *dev, bool deact nrfy_spim_disable(reg); } - if (!pm_device_runtime_is_enabled(dev)) { - release_clock(dev); - } - pm_device_runtime_put_async(dev, K_NO_WAIT); } @@ -640,10 +506,6 @@ static int transceive(const struct device *dev, error = configure(dev, spi_cfg); - if (error == 0 && !pm_device_runtime_is_enabled(dev)) { - error = request_clock(dev); - } - if (error == 0) { dev_data->busy = true; @@ -772,21 +634,7 @@ static int spim_resume(const struct device *dev) return -EAGAIN; } -#if SPIM_CROSS_DOMAIN_SUPPORTED - if (dev_config->cross_domain && spim_has_cross_domain_connection(dev_config)) { -#if SPIM_CROSS_DOMAIN_PINS_HANDLE - int err; - - err = nrf_sys_event_request_global_constlat(); - (void)err; - __ASSERT_NO_MSG(err >= 0); -#else - __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); -#endif - } -#endif - - return pm_device_runtime_is_enabled(dev) ? request_clock(dev) : 0; + return 0; } static void spim_suspend(const struct device *dev) @@ -799,26 +647,8 @@ static void spim_suspend(const struct device *dev) dev_data->initialized = false; } - if (pm_device_runtime_is_enabled(dev)) { - release_clock(dev); - } - spi_context_cs_put_all(&dev_data->ctx); -#if SPIM_CROSS_DOMAIN_SUPPORTED - if (dev_config->cross_domain && spim_has_cross_domain_connection(dev_config)) { -#if SPIM_CROSS_DOMAIN_PINS_HANDLE - int err; - - err = nrf_sys_event_release_global_constlat(); - (void)err; - __ASSERT_NO_MSG(err >= 0); -#else - __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); -#endif - } -#endif - (void)pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_SLEEP); } @@ -905,14 +735,6 @@ static int spi_nrfx_deinit(const struct device *dev) ()) \ )) -/* Get initialization priority of an instance. Instances that requires clock control - * which is using nrfs (IPC) are initialized later. - */ -#define SPIM_INIT_PRIORITY(idx) \ - COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \ - (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \ - (CONFIG_SPI_INIT_PRIORITY)) - #define SPI_NRFX_SPIM_DEFINE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(SPIM(idx)); \ NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(SPIM(idx)); \ @@ -964,17 +786,6 @@ static int spi_nrfx_deinit(const struct device *dev) .wake_pin = NRF_DT_GPIOS_TO_PSEL_OR(SPIM(idx), wake_gpios, \ WAKE_PIN_NOT_USED), \ .wake_gpiote = WAKE_GPIOTE_INSTANCE(SPIM(idx)), \ - IF_ENABLED(SPIM_ANY_FAST, \ - (.clk_dev = DEVICE_DT_GET_OR_NULL( \ - DT_CLOCKS_CTLR(SPIM(idx))), \ - .clk_spec = { \ - .frequency = NRF_CLOCK_CONTROL_FREQUENCY_MAX, \ - },)) \ - IF_ENABLED(SPIM_PINS_CROSS_DOMAIN(_, /*empty*/, idx, _), \ - (.cross_domain = true, \ - .default_port = \ - DT_PROP_OR(DT_PHANDLE(SPIM(idx), \ - default_gpio_port), port, -1),)) \ .mem_reg = DMM_DEV_TO_REG(SPIM(idx)), \ }; \ BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \ @@ -987,7 +798,7 @@ static int spi_nrfx_deinit(const struct device *dev) PM_DEVICE_DT_GET(SPIM(idx)), \ &spi_##idx##_data, \ &spi_##idx##z_config, \ - POST_KERNEL, SPIM_INIT_PRIORITY(idx), \ + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ &spi_nrfx_driver_api) #define COND_NRF_SPIM_DEVICE(unused, prefix, i, _) \ diff --git a/drivers/spi/spi_nrfx_spis.c b/drivers/spi/spi_nrfx_spis.c index 64c9a6f14c45..0861ed3c2f54 100644 --- a/drivers/spi/spi_nrfx_spis.c +++ b/drivers/spi/spi_nrfx_spis.c @@ -20,14 +20,6 @@ LOG_MODULE_REGISTER(spi_nrfx_spis, CONFIG_SPI_LOG_LEVEL); #include "spi_context.h" -#if NRF_DT_INST_ANY_IS_FAST -/* If fast instances are used then system managed device PM cannot be used because - * it may call PM actions from locked context and fast SPIM PM actions can only be - * called from a thread context. - */ -BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED)); -#endif - /* * Current factors requiring use of DT_NODELABEL: * @@ -39,28 +31,6 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED)); #define SPIS(idx) DT_NODELABEL(SPIS_NODE(idx)) #define SPIS_PROP(idx, prop) DT_PROP(SPIS(idx), prop) #define SPIS_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIS(idx), prop) -#define SPIS_IS_FAST(idx) NRF_DT_IS_FAST(SPIS(idx)) - -#define SPIS_PINS_CROSS_DOMAIN(unused, prefix, idx, _) \ - COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(SPIS(prefix##idx)), \ - (SPIS_PROP(idx, cross_domain_pins_supported)), \ - (0)) - -#if NRFX_FOREACH_PRESENT(SPIS, SPIS_PINS_CROSS_DOMAIN, (||), (0)) -#include -/* Certain SPIM instances support usage of cross domain pins in form of dedicated pins on - * a port different from the default one. - */ -#define SPIS_CROSS_DOMAIN_SUPPORTED 1 -#endif - -#if SPIS_CROSS_DOMAIN_SUPPORTED && defined(CONFIG_NRF_SYS_EVENT) -#include -/* To use cross domain pins, constant latency mode needs to be applied, which is - * handled via nrf_sys_event requests. - */ -#define SPIS_CROSS_DOMAIN_PINS_HANDLE 1 -#endif struct spi_nrfx_data { struct spi_context ctx; @@ -81,38 +51,8 @@ struct spi_nrfx_config { const struct pinctrl_dev_config *pcfg; struct gpio_dt_spec wake_gpio; void *mem_reg; -#if SPIS_CROSS_DOMAIN_SUPPORTED - bool cross_domain; - int8_t default_port; -#endif }; -#if SPIS_CROSS_DOMAIN_SUPPORTED -static bool spis_has_cross_domain_connection(const struct spi_nrfx_config *config) -{ - const struct pinctrl_dev_config *pcfg = config->pcfg; - const struct pinctrl_state *state; - int ret; - - ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state); - if (ret < 0) { - LOG_ERR("Unable to read pin state"); - return false; - } - - for (uint8_t i = 0U; i < state->pin_cnt; i++) { - uint32_t pin = NRF_GET_PIN(state->pins[i]); - - if ((pin != NRF_PIN_DISCONNECTED) && - (nrf_gpio_pin_port_number_extract(&pin) != config->default_port)) { - return true; - } - } - - return false; -} -#endif - static inline nrf_spis_mode_t get_nrf_spis_mode(uint16_t operation) { if (SPI_MODE_GET(operation) & SPI_MODE_CPOL) { @@ -432,20 +372,6 @@ static void spi_nrfx_suspend(const struct device *dev) nrf_spis_disable(dev_config->spis.p_reg); } -#if SPIS_CROSS_DOMAIN_SUPPORTED - if (dev_config->cross_domain && spis_has_cross_domain_connection(dev_config)) { -#if SPIS_CROSS_DOMAIN_PINS_HANDLE - int err; - - err = nrf_sys_event_release_global_constlat(); - (void)err; - __ASSERT_NO_MSG(err >= 0); -#else - __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); -#endif - } -#endif - (void)pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_SLEEP); } @@ -455,20 +381,6 @@ static void spi_nrfx_resume(const struct device *dev) (void)pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_DEFAULT); -#if SPIS_CROSS_DOMAIN_SUPPORTED - if (dev_config->cross_domain && spis_has_cross_domain_connection(dev_config)) { -#if SPIS_CROSS_DOMAIN_PINS_HANDLE - int err; - - err = nrf_sys_event_request_global_constlat(); - (void)err; - __ASSERT_NO_MSG(err >= 0); -#else - __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); -#endif - } -#endif - if (dev_config->wake_gpio.port == NULL) { nrf_spis_enable(dev_config->spis.p_reg); } @@ -587,18 +499,11 @@ static int spi_nrfx_init(const struct device *dev) .max_buf_len = BIT_MASK(SPIS_PROP(idx, easydma_maxcnt_bits)), \ .wake_gpio = GPIO_DT_SPEC_GET_OR(SPIS(idx), wake_gpios, {0}), \ .mem_reg = DMM_DEV_TO_REG(SPIS(idx)), \ - IF_ENABLED(SPIS_PINS_CROSS_DOMAIN(_, /*empty*/, idx, _), \ - (.cross_domain = true, \ - .default_port = \ - DT_PROP_OR(DT_PHANDLE(SPIS(idx), \ - default_gpio_port), port, -1),)) \ }; \ BUILD_ASSERT(!DT_NODE_HAS_PROP(SPIS(idx), wake_gpios) || \ !(DT_GPIO_FLAGS(SPIS(idx), wake_gpios) & GPIO_ACTIVE_LOW),\ "WAKE line must be configured as active high"); \ - PM_DEVICE_DT_DEFINE(SPIS(idx), spi_nrfx_pm_action, \ - COND_CODE_1(SPIS_IS_FAST(idx), (0), \ - (PM_DEVICE_ISR_SAFE))); \ + PM_DEVICE_DT_DEFINE(SPIS(idx), spi_nrfx_pm_action, PM_DEVICE_ISR_SAFE);\ SPI_DEVICE_DT_DEFINE(SPIS(idx), \ spi_nrfx_init, \ PM_DEVICE_DT_GET(SPIS(idx)), \ diff --git a/drivers/timer/Kconfig.nrf_grtc b/drivers/timer/Kconfig.nrf_grtc index 082c15333dcb..ab230245ebfd 100644 --- a/drivers/timer/Kconfig.nrf_grtc +++ b/drivers/timer/Kconfig.nrf_grtc @@ -6,6 +6,7 @@ menuconfig NRF_GRTC_TIMER default y depends on DT_HAS_NORDIC_NRF_GRTC_ENABLED select TICKLESS_CAPABLE + select SYSTEM_TIMER_HAS_DISABLE_SUPPORT select TIMER_HAS_64BIT_CYCLE_COUNTER select NRFX_GRTC help @@ -56,4 +57,29 @@ config NRF_GRTC_TIMER_AUTO_KEEP_ALIVE This feature prevents the SYSCOUNTER from sleeping when any core is in active state. +if NRF_GRTC_START_SYSCOUNTER + +choice NRF_GRTC_TIMER_SOURCE + prompt "nRF GRTC clock source" + # Default to LFLPRC if CLOCK_CONTROL_NRF_K32SRC_RC for backwards compatibility + default NRF_GRTC_TIMER_SOURCE_LFLPRC if CLOCK_CONTROL_NRF_K32SRC_RC + # Default to LFXO if present as this allows GRTC to run in SYSTEM OFF + default NRF_GRTC_TIMER_SOURCE_LFXO + # Default to SYSTEM_LFCLK if LFXO is not present + default NRF_GRTC_TIMER_SOURCE_SYSTEM_LFCLK + +config NRF_GRTC_TIMER_SOURCE_LFXO + bool "Use Low Frequency XO as clock source" + depends on $(dt_nodelabel_enabled,lfxo) + +config NRF_GRTC_TIMER_SOURCE_SYSTEM_LFCLK + bool "Use System Low Frequency clock as clock source" + +config NRF_GRTC_TIMER_SOURCE_LFLPRC + bool "Use Low Frequency Low Power RC as clock source" + +endchoice # NRF_GRTC_TIMER_SOURCE + +endif # NRF_GRTC_START_SYSCOUNTER + endif # NRF_GRTC_TIMER diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index 4e1223635085..94ec7e3a240f 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -49,10 +49,9 @@ #define COUNTER_SPAN (GRTC_SYSCOUNTERL_VALUE_Msk | ((uint64_t)GRTC_SYSCOUNTERH_VALUE_Msk << 32)) #define MAX_ABS_TICKS (COUNTER_SPAN / CYC_PER_TICK) -#define MAX_TICKS \ - (((COUNTER_SPAN / CYC_PER_TICK) > INT_MAX) ? INT_MAX : (COUNTER_SPAN / CYC_PER_TICK)) - -#define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK) +/* To allow use of CCADD we need to limit max cycles to 31 bits. */ +#define MAX_REL_CYCLES BIT_MASK(31) +#define MAX_REL_TICKS (MAX_REL_CYCLES / CYC_PER_TICK) #if DT_NODE_HAS_STATUS_OKAY(LFCLK_NODE) #define LFCLK_FREQUENCY_HZ DT_PROP(LFCLK_NODE, clock_frequency) @@ -60,14 +59,21 @@ #define LFCLK_FREQUENCY_HZ CONFIG_CLOCK_CONTROL_NRF_K32SRC_FREQUENCY #endif +/* Threshold used to determine if there is a risk of unexpected GRTC COMPARE event coming + * from previous CC value. + */ +#define LATENCY_THR_TICKS 200 + #if defined(CONFIG_TEST) const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE); #endif static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_context); -static struct k_spinlock lock; static uint64_t last_count; /* Time (SYSCOUNTER value) @last sys_clock_announce() */ +static uint64_t last_elapsed; +static uint64_t cc_value; /* Value that is expected to be in CC register. */ +static uint64_t expired_cc; /* Value that is expected to be in CC register. */ static atomic_t int_mask; static uint8_t ext_channels_allocated; static uint64_t grtc_start_value; @@ -151,16 +157,11 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte { ARG_UNUSED(id); ARG_UNUSED(p_context); - uint64_t dticks; - uint64_t now = counter(); - - if (unlikely(now < cc_val)) { - return; - } + uint32_t dticks; dticks = counter_sub(cc_val, last_count) / CYC_PER_TICK; - - last_count += dticks * CYC_PER_TICK; + last_count += (dticks * CYC_PER_TICK); + expired_cc = cc_val; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { /* protection is not needed because we are in the GRTC interrupt @@ -169,6 +170,7 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte system_timeout_set_abs(last_count + CYC_PER_TICK); } + last_elapsed = 0; sys_clock_announce((int32_t)dticks); } @@ -335,18 +337,13 @@ int z_nrf_grtc_timer_capture_prepare(int32_t chan) int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time) { - /* TODO: The implementation should probably go to nrfx_grtc and this - * should be just a wrapper for some nrfx_grtc_syscounter_capture_read. - */ - uint64_t capt_time; nrfx_err_t result; IS_CHANNEL_ALLOWED_ASSERT(chan); - /* TODO: Use `nrfy_grtc_sys_counter_enable_check` when available (NRFX-2480) */ - if (NRF_GRTC->CC[chan].CCEN == GRTC_CC_CCEN_ACTIVE_Enable) { - /* If the channel is enabled (.CCEN), it means that there was no capture + if (nrfx_grtc_sys_counter_cc_enable_check(chan)) { + /* If the channel is enabled, it means that there was no capture * triggering event. */ return -EBUSY; @@ -371,7 +368,12 @@ uint64_t z_nrf_grtc_timer_startup_value_get(void) #if defined(CONFIG_POWEROFF) && defined(CONFIG_NRF_GRTC_START_SYSCOUNTER) int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) { + if (!nrfx_grtc_init_check()) { + return -ENOTSUP; + } + nrfx_err_t err_code; + static struct k_spinlock lock; static uint8_t systemoff_channel; uint64_t now = counter(); nrfx_grtc_sleep_config_t sleep_cfg; @@ -434,20 +436,12 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) uint32_t sys_clock_cycle_get_32(void) { - k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t ret = (uint32_t)counter(); - - k_spin_unlock(&lock, key); - return ret; + return (uint32_t)counter(); } uint64_t sys_clock_cycle_get_64(void) { - k_spinlock_key_t key = k_spin_lock(&lock); - uint64_t ret = counter(); - - k_spin_unlock(&lock, key); - return ret; + return counter(); } uint32_t sys_clock_elapsed(void) @@ -456,24 +450,57 @@ uint32_t sys_clock_elapsed(void) return 0; } - return (uint32_t)(counter_sub(counter(), last_count) / CYC_PER_TICK); + last_elapsed = counter_sub(counter(), last_count); + + return (uint32_t)(last_elapsed / CYC_PER_TICK); +} + +#if !defined(CONFIG_GEN_SW_ISR_TABLE) +ISR_DIRECT_DECLARE(nrfx_grtc_direct_irq_handler) +{ + nrfx_grtc_irq_handler(); + ISR_DIRECT_PM(); + return 1; +} +#endif + +void sys_clock_disable(void) +{ + nrfx_grtc_uninit(); +#if defined(CONFIG_CLOCK_CONTROL_NRF) + int err; + struct onoff_manager *mgr = + z_nrf_clock_control_get_onoff((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_LFCLK); + + err = onoff_release(mgr); + __ASSERT_NO_MSG(err >= 0); + + nrfx_coredep_delay_us(1000); +#endif } static int sys_clock_driver_init(void) { nrfx_err_t err_code; +#if defined(CONFIG_GEN_SW_ISR_TABLE) IRQ_CONNECT(DT_IRQN(GRTC_NODE), DT_IRQ(GRTC_NODE, priority), nrfx_isr, nrfx_grtc_irq_handler, 0); +#else + IRQ_DIRECT_CONNECT(DT_IRQN(GRTC_NODE), DT_IRQ(GRTC_NODE, priority), + nrfx_grtc_direct_irq_handler, 0); + irq_enable(DT_IRQN(GRTC_NODE)); +#endif #if defined(CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) && NRF_GRTC_HAS_CLKSEL -#if defined(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC) +#if defined(CONFIG_NRF_GRTC_TIMER_SOURCE_LFLPRC) /* Switch to LFPRC as the low-frequency clock source. */ nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFLPRC); -#elif DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lfxo)) +#elif defined(CONFIG_NRF_GRTC_TIMER_SOURCE_LFXO) /* Switch to LFXO as the low-frequency clock source. */ nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFXO); #else + /* Use LFCLK as the low-frequency clock source. */ nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFCLK); #endif #endif @@ -497,11 +524,20 @@ static int sys_clock_driver_init(void) last_count = (counter() / CYC_PER_TICK) * CYC_PER_TICK; grtc_start_value = last_count; + expired_cc = UINT64_MAX; + nrfx_grtc_channel_callback_set(system_clock_channel_data.channel, + sys_clock_timeout_handler, NULL); + int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { system_timeout_set_relative(CYC_PER_TICK); } + return 0; +} + +static int grtc_post_init(void) +{ #if defined(CONFIG_CLOCK_CONTROL_NRF) static const enum nrf_lfclk_start_mode mode = IS_ENABLED(CONFIG_SYSTEM_CLOCK_NO_WAIT) @@ -555,18 +591,47 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) return; } - ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : MIN(MAX_TICKS, MAX(ticks, 0)); + uint32_t ch = system_clock_channel_data.channel; + + if ((cc_value == expired_cc) && (ticks <= MAX_REL_TICKS)) { + uint32_t cyc = ticks * CYC_PER_TICK; + + if (cyc == 0) { + /* GRTC will expire anyway since HW ensures that past value triggers an + * event but we need to ensure to always progress the cc_value as this + * if condition expects that cc_value will change after each call to + * set_timeout function. + */ + cyc = 1; + } + + /* If it's the first timeout setting after previous expiration and timeout + * is short so fast method can be used which utilizes relative CC configuration. + */ + cc_value += cyc; + nrfx_grtc_syscounter_cc_rel_set(ch, cyc, NRFX_GRTC_CC_RELATIVE_COMPARE); + return; + } - uint64_t delta_time = ticks * CYC_PER_TICK; + uint64_t cyc = (uint64_t)ticks * CYC_PER_TICK; + bool safe_setting = false; + uint64_t prev_cc_val = cc_value; + uint64_t now = last_count + last_elapsed; - uint64_t target_time = counter() + delta_time; + cc_value = now + cyc; - /* Rounded down target_time to the tick boundary - * (but not less than one tick after the last) + /* In case of timeout abort it may happen that CC is being set to a value + * that later than previous CC. If previous CC value is not far in the + * future, there is a risk that COMPARE event will be triggered for that + * previous CC value. If there is such risk safe procedure must be applied + * which is more time consuming but ensures that there will be no spurious + * event. */ - target_time = MAX((target_time - last_count)/CYC_PER_TICK, 1)*CYC_PER_TICK + last_count; + if (prev_cc_val < cc_value) { + safe_setting = (int64_t)(prev_cc_val - now) < LATENCY_THR_TICKS; + } - system_timeout_set_abs(target_time); + nrfx_grtc_syscounter_cc_abs_set(ch, cc_value, safe_setting); } #if defined(CONFIG_NRF_GRTC_TIMER_APP_DEFINED_INIT) @@ -575,5 +640,6 @@ int nrf_grtc_timer_clock_driver_init(void) return sys_clock_driver_init(); } #else -SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); +SYS_INIT(sys_clock_driver_init, EARLY, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); +SYS_INIT(grtc_post_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); #endif diff --git a/drivers/usb/udc/Kconfig.dwc2 b/drivers/usb/udc/Kconfig.dwc2 index 1bb0e99fedde..ff3b169e66a5 100644 --- a/drivers/usb/udc/Kconfig.dwc2 +++ b/drivers/usb/udc/Kconfig.dwc2 @@ -12,23 +12,22 @@ config UDC_DWC2 help DWC2 USB device controller driver. +if UDC_DWC2 + config UDC_DWC2_DMA bool "DWC2 USB DMA support" default y - depends on UDC_DWC2 help Enable Buffer DMA if DWC2 USB controller supports Internal DMA. config UDC_DWC2_HIBERNATION bool "DWC2 USB Hibernation support" default y - depends on UDC_DWC2 help Enable Hibernation if DWC2 USB controller supports hibernation. config UDC_DWC2_PTI bool "DWC2 USB Periodic Transfer Interrupt" - depends on UDC_DWC2 help Ignore frame number when scheduling isochronous endpoints. Use this when isochronous transfers should finish only after receiving token @@ -38,24 +37,23 @@ config UDC_DWC2_PTI config UDC_DWC2_STACK_SIZE int "UDC DWC2 driver internal thread stack size" - depends on UDC_DWC2 default 512 help DWC2 driver internal thread stack size. config UDC_DWC2_THREAD_PRIORITY int "UDC DWC2 driver thread priority" - depends on UDC_DWC2 default 8 help DWC2 driver thread priority. config UDC_DWC2_USBHS_VBUS_READY_TIMEOUT int "UDC DWC2 USBHS VBUS ready event timeout in ms" - depends on UDC_DWC2 - depends on NRFS_HAS_VBUS_DETECTOR_SERVICE + depends on SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX || SOC_SERIES_NRF92X default 0 help UDC DWC2 USBHS VBUS ready event timeout. If the VBUS is not ready and the Nordic USBHS controller is used, the udc_enable() is blocked for this amount of time. Set it to zero to wait forever. + +endif # UDC_DWC2 diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 35fb78adecfa..eb7368e1178f 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -434,6 +434,11 @@ static void dwc2_ensure_setup_ready(const struct device *dev) } else { struct udc_dwc2_data *const priv = udc_get_private(dev); + if (udc_ep_is_busy(udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT))) { + /* There is already buffer queued */ + return; + } + /* Enable EP0 OUT only if there is no pending EP0 IN transfer * after which the stack has to enable EP0 OUT. */ @@ -1581,9 +1586,11 @@ static int dwc2_unset_dedicated_fifo(const struct device *dev, *diepctl &= ~USB_DWC2_DEPCTL_TXFNUM_MASK; if (priv->dynfifosizing) { - if (priv->txf_set & ~BIT_MASK(ep_idx)) { - LOG_WRN("Some of the FIFOs higher than %u are set, %lx", - ep_idx, priv->txf_set & ~BIT_MASK(ep_idx)); + uint16_t higher_mask = ~BIT_MASK(ep_idx + 1); + + if (priv->txf_set & higher_mask) { + LOG_WRN("Some of the FIFOs higher than %u are set, %x", + ep_idx, priv->txf_set & higher_mask); return 0; } @@ -1723,7 +1730,19 @@ static int udc_dwc2_ep_deactivate(const struct device *dev, mem_addr_t dxepctl_reg; uint32_t dxepctl; - dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr); + if (priv->hibernated) { + /* If usbd_disable() is called when core is hibernated, modify + * backup registers instead of real ones. + */ + if (USB_EP_DIR_IS_OUT(cfg->addr)) { + dxepctl_reg = (mem_addr_t)&priv->backup.doepctl[ep_idx]; + } else { + dxepctl_reg = (mem_addr_t)&priv->backup.diepctl[ep_idx]; + } + } else { + dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr); + } + dxepctl = sys_read32(dxepctl_reg); if (dxepctl & USB_DWC2_DEPCTL_USBACTEP) { diff --git a/drivers/usb/udc/udc_dwc2_vendor_quirks.h b/drivers/usb/udc/udc_dwc2_vendor_quirks.h index 330ff8d113f1..9b2d26b89008 100644 --- a/drivers/usb/udc/udc_dwc2_vendor_quirks.h +++ b/drivers/usb/udc/udc_dwc2_vendor_quirks.h @@ -213,10 +213,21 @@ static inline int usbhs_enable_core(const struct device *dev) return 0; } +static inline int usbhs_enable_pullup(const struct device *dev) +{ + /* Core is ready to handle connection, enable D+ pull-up */ + nrfs_usb_dplus_pullup_enable((void *)dev); + + return 0; +} + static inline int usbhs_disable_core(const struct device *dev) { NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + /* Disable D+ pull-up until next post enable quirk */ + nrfs_usb_dplus_pullup_disable((void *)dev); + /* Disable interrupts */ wrapper->INTENCLR = 1UL; @@ -299,6 +310,7 @@ static inline int usbhs_pre_hibernation_exit(const struct device *dev) const struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ .init = usbhs_enable_nrfs_service, \ .pre_enable = usbhs_enable_core, \ + .post_enable = usbhs_enable_pullup, \ .disable = usbhs_disable_core, \ .shutdown = usbhs_disable_nrfs_service, \ .irq_clear = usbhs_irq_clear, \ @@ -381,6 +393,10 @@ static inline int usbhs_enable_core(const struct device *dev) k_timeout_t timeout = K_FOREVER; int err; + if (CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT) { + timeout = K_MSEC(CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT); + } + if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_NO_WAIT)) { LOG_WRN("VBUS is not ready, block udc_enable()"); if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, timeout)) { diff --git a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi index 9b37c302872b..2021d25580ae 100644 --- a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi +++ b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi @@ -108,6 +108,15 @@ config NRF70_AP_MODE depends on WIFI_NM_WPA_SUPPLICANT_AP default y if WIFI_USAGE_MODE_AP || WIFI_USAGE_MODE_STA_AP +config NRF70_ENABLE_DUAL_VIF + bool "Dual virtual Wi-Fi interfaces" + default y if WIFI_NM_MAX_MANAGED_INTERFACES = 2 + depends on (WIFI_NRF7002 || WIFI_NRF7001) && NET_L2_ETHERNET + help + Enable support for two virtual Wi-Fi interfaces (VIFs). + When enabled, the driver can operate two VIFs simultaneously, + allowing use cases such as one interface in AP mode and another in STA mode. + config NRF70_P2P_MODE bool "P2P support in driver" @@ -165,6 +174,7 @@ config NRF_WIFI_LOW_POWER config NRF70_TCP_IP_CHECKSUM_OFFLOAD bool "TCP/IP checksum offload" + depends on !NRF71_ON_IPC default y config NRF70_REG_DOMAIN @@ -655,28 +665,27 @@ config WIFI_NRF70_SCAN_TIMEOUT_S int "Scan timeout in seconds" default 30 -menu "nRF Wi-Fi operation band(s)" - visible if !NRF70_2_4G_ONLY +choice NRF_WIFI_OP_BAND + prompt "nRF Wi-Fi operation bands" + default NRF_WIFI_2G_BAND if NRF70_2_4G_ONLY + default NRF_WIFI_ALL_BAND + +config NRF_WIFI_ALL_BAND + bool "Set operation band to all supported bands" config NRF_WIFI_2G_BAND bool "Set operation band to 2.4GHz" - default y if NRF70_2_4G_ONLY config NRF_WIFI_5G_BAND bool "Set operation band to 5GHz" - depends on !NRF70_2_4G_ONLY - -config NRF_WIFI_OP_BAND - int "Options to set operation band" - default 1 if NRF_WIFI_2G_BAND - default 2 if NRF_WIFI_5G_BAND - default 3 - help - Set this option to select frequency band - 1 - 2.4GHz - 2 - 5GHz - 3 - All ( 2.4GHz and 5GHz ) -endmenu +if NRF71_ON_IPC +config NRF_WIFI_6G_BAND + bool "Set operation band to 6GHz" + +config NRF_WIFI_DUAL_BAND + bool "Set operation band to 2.4GHz and 5GHz" +endif # NRF71_ON_IPC +endchoice config NRF_WIFI_IFACE_MTU int "MTU for Wi-Fi interface" diff --git a/drivers/wifi/nrf_wifi/inc/fmac_main.h b/drivers/wifi/nrf_wifi/inc/fmac_main.h index 7a863d8b614a..799beff1fbaf 100644 --- a/drivers/wifi/nrf_wifi/inc/fmac_main.h +++ b/drivers/wifi/nrf_wifi/inc/fmac_main.h @@ -31,11 +31,19 @@ #else #include #endif /* !CONFIG_NRF70_RADIO_TEST */ - +#ifdef CONFIG_NRF71_ON_IPC +#include +#else #include +#endif /* CONFIG_NRF71_ON_IPC */ #define NRF70_DRIVER_VERSION "1."KERNEL_VERSION_STRING +/* Calculate compile-time maximum for vendor stats */ +#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR +#define MAX_VENDOR_STATS ((sizeof(struct rpu_sys_fw_stats) / sizeof(uint32_t)) + 1) +#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */ + #ifndef CONFIG_NRF70_OFFLOADED_RAW_TX #ifndef CONFIG_NRF70_RADIO_TEST struct nrf_wifi_vif_ctx_zep { @@ -61,6 +69,10 @@ struct nrf_wifi_vif_ctx_zep { bool set_if_event_received; int set_if_status; #ifdef CONFIG_NET_STATISTICS_ETHERNET +#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR + struct net_stats_eth_vendor eth_stats_vendor_data[MAX_VENDOR_STATS]; + char vendor_key_strings[MAX_VENDOR_STATS][16]; +#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */ struct net_stats_eth eth_stats; #endif /* CONFIG_NET_STATISTICS_ETHERNET */ #if defined(CONFIG_NRF70_STA_MODE) || defined(CONFIG_NRF70_RAW_DATA_RX) diff --git a/drivers/wifi/nrf_wifi/off_raw_tx/src/off_raw_tx_api.c b/drivers/wifi/nrf_wifi/off_raw_tx/src/off_raw_tx_api.c index 17825511787b..1e53f70c111f 100644 --- a/drivers/wifi/nrf_wifi/off_raw_tx/src/off_raw_tx_api.c +++ b/drivers/wifi/nrf_wifi/off_raw_tx/src/off_raw_tx_api.c @@ -128,6 +128,25 @@ static int bytes_from_str(uint8_t *buf, int buf_len, const char *src) } #endif /* CONFIG_WIFI_FIXED_MAC_ADDRESS_ENABLED */ +static enum op_band get_nrf_wifi_op_band(void) +{ + if (IS_ENABLED(CONFIG_NRF_WIFI_2G_BAND)) { + return BAND_24G; + } +#ifdef CONFIG_NRF71_ON_IPC + if (IS_ENABLED(CONFIG_NRF_WIFI_5G_BAND)) { + return BAND_5G; + } + if (IS_ENABLED(CONFIG_NRF_WIFI_6G_BAND)) { + return BAND_6G; + } + if (IS_ENABLED(CONFIG_NRF_WIFI_DUAL_BAND)) { + return BAND_DUAL; + } +#endif /* CONFIG_NRF71_ON_IPC */ + return BAND_ALL; +} + int nrf70_off_raw_tx_init(uint8_t *mac_addr, unsigned char *country_code) { enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; @@ -138,6 +157,7 @@ int nrf70_off_raw_tx_init(uint8_t *mac_addr, unsigned char *country_code) struct nrf_wifi_board_params board_params; unsigned int fw_ver = 0; k_spinlock_key_t key; + enum op_band op_band = get_nrf_wifi_op_band(); /* The OSAL layer needs to be initialized before any other initialization * so that other layers (like FW IF,HW IF etc) have access to OS ops @@ -202,7 +222,7 @@ int nrf70_off_raw_tx_init(uint8_t *mac_addr, unsigned char *country_code) HW_SLEEP_ENABLE, #endif /* CONFIG_NRF_WIFI_LOW_POWER */ NRF_WIFI_DEF_PHY_CALIB, - CONFIG_NRF_WIFI_OP_BAND, + op_band, IS_ENABLED(CONFIG_NRF_WIFI_BEAMFORMING), &ctrl_params, &ceil_params, diff --git a/drivers/wifi/nrf_wifi/src/debug_shell.c b/drivers/wifi/nrf_wifi/src/debug_shell.c index 70fb77d6ed0d..b6ac79bf7724 100644 --- a/drivers/wifi/nrf_wifi/src/debug_shell.c +++ b/drivers/wifi/nrf_wifi/src/debug_shell.c @@ -9,7 +9,11 @@ */ #include #include +#ifdef NRF71_ON_IPC +#include +#else #include "host_rpu_umac_if.h" +#endif #include "fmac_main.h" extern struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep; diff --git a/drivers/wifi/nrf_wifi/src/fmac_main.c b/drivers/wifi/nrf_wifi/src/fmac_main.c index 125ffd7a9a10..47ca53d5a61c 100644 --- a/drivers/wifi/nrf_wifi/src/fmac_main.c +++ b/drivers/wifi/nrf_wifi/src/fmac_main.c @@ -69,9 +69,10 @@ BUILD_ASSERT(CONFIG_NRF70_MAX_TX_AGGREGATION <= 15, "Max TX aggregation is 15"); BUILD_ASSERT(CONFIG_NRF70_RX_NUM_BUFS >= 1, "At least one RX buffer is required"); +#ifndef CONFIG_NRF71_ON_IPC BUILD_ASSERT(RPU_PKTRAM_SIZE - TOTAL_RX_SIZE >= TOTAL_TX_SIZE, "Packet RAM overflow: not enough memory for TX"); - +#endif /* CONFIG_NRF71_ON_IPC */ BUILD_ASSERT(CONFIG_NRF70_TX_MAX_DATA_SIZE >= MAX_TX_FRAME_SIZE, "TX buffer size must be at least as big as the MTU and headroom"); @@ -503,12 +504,9 @@ void reg_change_callbk_fn(void *vif_ctx, } #endif /* !CONFIG_NRF70_RADIO_TEST */ -#ifdef CONFIG_NRF71_ON_IPC -#define MAX_TX_PWR(label) DT_PROP(DT_NODELABEL(wifi), label) * 4 -#else +#ifndef CONFIG_NRF71_ON_IPC /* DTS uses 1dBm as the unit for TX power, while the RPU uses 0.25dBm */ #define MAX_TX_PWR(label) DT_PROP(DT_NODELABEL(nrf70), label) * 4 -#endif /* CONFIG_NRF71_ON_IPC */ void configure_tx_pwr_settings(struct nrf_wifi_tx_pwr_ctrl_params *tx_pwr_ctrl_params, struct nrf_wifi_tx_pwr_ceil_params *tx_pwr_ceil_params) @@ -587,13 +585,34 @@ void configure_board_dep_params(struct nrf_wifi_board_params *board_params) board_params->pcb_loss_5g_band3 = CONFIG_NRF70_PCB_LOSS_5G_BAND3; #endif /* CONFIG_NRF70_2_4G_ONLY */ } +#endif /* CONFIG_NRF71_ON_IPC */ + +static enum op_band get_nrf_wifi_op_band(void) +{ + if (IS_ENABLED(CONFIG_NRF_WIFI_2G_BAND)) { + return BAND_24G; + } +#ifdef CONFIG_NRF71_ON_IPC + if (IS_ENABLED(CONFIG_NRF_WIFI_5G_BAND)) { + return BAND_5G; + } + + if (IS_ENABLED(CONFIG_NRF_WIFI_6G_BAND)) { + return BAND_6G; + } + if (IS_ENABLED(CONFIG_NRF_WIFI_DUAL_BAND)) { + return BAND_DUAL; + } +#endif /* CONFIG_NRF71_ON_IPC */ + return BAND_ALL; +} enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep) { enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; void *rpu_ctx = NULL; - enum op_band op_band = CONFIG_NRF_WIFI_OP_BAND; + enum op_band op_band = get_nrf_wifi_op_band(); #ifdef CONFIG_NRF_WIFI_LOW_POWER int sleep_type = -1; @@ -606,7 +625,6 @@ enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv struct nrf_wifi_tx_pwr_ctrl_params tx_pwr_ctrl_params; struct nrf_wifi_tx_pwr_ceil_params tx_pwr_ceil_params; struct nrf_wifi_board_params board_params; - unsigned int fw_ver = 0; #if defined(CONFIG_NRF70_SR_COEX_SLEEP_CTRL_GPIO_CTRL) && \ @@ -654,10 +672,12 @@ enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv NRF_WIFI_UMAC_VER_MIN(fw_ver), NRF_WIFI_UMAC_VER_EXTRA(fw_ver)); +#ifndef CONFIG_NRF71_ON_IPC configure_tx_pwr_settings(&tx_pwr_ctrl_params, &tx_pwr_ceil_params); configure_board_dep_params(&board_params); +#endif /* CONFIG_NRF71_ON_IPC */ #if defined(CONFIG_NRF70_SR_COEX_SLEEP_CTRL_GPIO_CTRL) && \ defined(CONFIG_NRF70_SYSTEM_MODE) @@ -743,8 +763,28 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) struct nrf_wifi_data_config_params data_config = { 0 }; struct rx_buf_pool_params rx_buf_pools[MAX_NUM_OF_RX_QUEUES]; struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = dev->data; + static unsigned char fixed_vif_cnt; + if (fixed_vif_cnt >= MAX_NUM_VIFS) { + LOG_ERR("%s: Max number of VIFs reached", __func__); + return -ENOMEM; + } + + /* Setup the linkage between the FMAC and the VIF contexts */ vif_ctx_zep->rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep; +#ifndef CONFIG_NRF70_RADIO_TEST + k_work_init_delayable(&vif_ctx_zep->scan_timeout_work, + nrf_wifi_scan_timeout_work); + k_work_init(&vif_ctx_zep->disp_scan_res_work, + nrf_wifi_disp_scan_res_work_handler); + + vif_ctx_zep->bss_max_idle_period = USHRT_MAX; +#endif /* !CONFIG_NRF70_RADIO_TEST */ + + if (fixed_vif_cnt++ > 0) { + /* FMAC is already initialized for VIF-0 */ + return 0; + } #ifdef CONFIG_NRF70_DATA_TX data_config.aggregation = aggregation; @@ -823,7 +863,6 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) rpu_drv_priv_zep.fmac_priv = nrf_wifi_rt_fmac_init(); #endif /* CONFIG_NRF70_RADIO_TEST */ - if (rpu_drv_priv_zep.fmac_priv == NULL) { LOG_ERR("%s: nrf_wifi_fmac_init failed", __func__); @@ -834,9 +873,14 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL; sys_fpriv = wifi_fmac_priv(rpu_drv_priv_zep.fmac_priv); +#ifdef CONFIG_NRF71_ON_IPC + /* TODO: Revisit this */ + sys_fpriv->max_ampdu_len_per_token = 8192; +#else sys_fpriv->max_ampdu_len_per_token = (RPU_PKTRAM_SIZE - (CONFIG_NRF70_RX_NUM_BUFS * CONFIG_NRF70_RX_MAX_DATA_SIZE)) / CONFIG_NRF70_MAX_TX_TOKENS; +#endif /* CONFIG_NRF71_ON_IPC */ /* Align to 4-byte */ sys_fpriv->max_ampdu_len_per_token &= ~0x3; @@ -852,17 +896,10 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) LOG_ERR("%s: nrf_wifi_fmac_dev_add_zep failed", __func__); goto fmac_deinit; } -#else - k_work_init_delayable(&vif_ctx_zep->scan_timeout_work, - nrf_wifi_scan_timeout_work); - k_work_init(&vif_ctx_zep->disp_scan_res_work, - nrf_wifi_disp_scan_res_work_handler); #endif /* CONFIG_NRF70_RADIO_TEST */ k_mutex_init(&rpu_drv_priv_zep.rpu_ctx_zep.rpu_lock); -#ifndef CONFIG_NRF70_RADIO_TEST - vif_ctx_zep->bss_max_idle_period = USHRT_MAX; -#endif /* !CONFIG_NRF70_RADIO_TEST */ + return 0; #ifdef CONFIG_NRF70_RADIO_TEST fmac_deinit: @@ -979,6 +1016,21 @@ ETH_NET_DEVICE_DT_INST_DEFINE(0, CONFIG_WIFI_INIT_PRIORITY, /* prio */ &wifi_offload_ops, /* api */ CONFIG_NRF_WIFI_IFACE_MTU); /*mtu */ +#ifdef CONFIG_NRF70_ENABLE_DUAL_VIF +/* Register second interface */ +ETH_NET_DEVICE_DT_INST_DEFINE(1, + nrf_wifi_drv_main_zep, /* init_fn */ + NULL, /* pm_action_cb */ + &rpu_drv_priv_zep.rpu_ctx_zep.vif_ctx_zep[1], /* data */ +#ifdef CONFIG_NRF70_STA_MODE + &wpa_supp_ops, /* cfg */ +#else /* CONFIG_NRF70_STA_MODE */ + NULL, /* cfg */ +#endif /* !CONFIG_NRF70_STA_MODE */ + CONFIG_WIFI_INIT_PRIORITY, /* prio */ + &wifi_offload_ops, /* api */ + CONFIG_NRF_WIFI_IFACE_MTU); /*mtu */ +#endif /* NRF70_ENABLE_DUAL_VIF */ #else DEVICE_DT_INST_DEFINE(0, nrf_wifi_drv_main_zep, /* init_fn */ diff --git a/drivers/wifi/nrf_wifi/src/fw_load.c b/drivers/wifi/nrf_wifi/src/fw_load.c index f09643a585a8..cce5a98372fc 100644 --- a/drivers/wifi/nrf_wifi/src/fw_load.c +++ b/drivers/wifi/nrf_wifi/src/fw_load.c @@ -17,13 +17,17 @@ LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL); #include +#ifndef CONFIG_NRF71_ON_IPC static const char fw_patch[] = { #include }; +#endif /* CONFIG_NRF71_ON_IPC */ enum nrf_wifi_status nrf_wifi_fw_load(void *rpu_ctx) { enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + +#ifndef CONFIG_NRF71_ON_IPC struct nrf_wifi_fmac_fw_info fw_info = { 0 }; status = nrf_wifi_fmac_fw_parse(rpu_ctx, fw_patch, sizeof(fw_patch), &fw_info); @@ -31,13 +35,15 @@ enum nrf_wifi_status nrf_wifi_fw_load(void *rpu_ctx) LOG_ERR("%s: nrf_wifi_fmac_fw_parse failed", __func__); return status; } -#ifndef CONFIG_NRF71_ON_IPC + /* Load the FW patches to the RPU */ status = nrf_wifi_fmac_fw_load(rpu_ctx, &fw_info); if (status != NRF_WIFI_STATUS_SUCCESS) { LOG_ERR("%s: nrf_wifi_fmac_fw_load failed", __func__); } +#else + status = NRF_WIFI_STATUS_SUCCESS; #endif /* !CONFIG_NRF71_ON_IPC */ return status; } diff --git a/drivers/wifi/nrf_wifi/src/net_if.c b/drivers/wifi/nrf_wifi/src/net_if.c index 4830d63c9d15..0662c6c80d09 100644 --- a/drivers/wifi/nrf_wifi/src/net_if.c +++ b/drivers/wifi/nrf_wifi/src/net_if.c @@ -824,8 +824,7 @@ int nrf_wifi_if_start_zep(const struct device *dev) } k_mutex_init(&vif_ctx_zep->vif_lock); - rpu_ctx_zep->vif_ctx_zep[vif_ctx_zep->vif_idx].if_type = - add_vif_info.iftype; + vif_ctx_zep->if_type = add_vif_info.iftype; /* Check if user has provided a valid MAC address, if not * fetch it from OTP. @@ -1214,6 +1213,16 @@ int nrf_wifi_if_set_config_zep(const struct device *dev, struct net_stats_eth *nrf_wifi_eth_stats_get(const struct device *dev) { struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; +#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR + struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; + struct rpu_sys_op_stats stats; + enum nrf_wifi_status status; + size_t fw_stats_size; + size_t num_uint32; + const uint8_t *fw_stats_bytes; + size_t i; + int vendor_idx = 0; +#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */ if (!dev) { LOG_ERR("%s Device not found", __func__); @@ -1226,6 +1235,69 @@ struct net_stats_eth *nrf_wifi_eth_stats_get(const struct device *dev) goto out; } +#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR + rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; + if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) { + LOG_ERR("%s: rpu_ctx_zep or rpu_ctx is NULL", __func__); + goto out; + } + + memset(&stats, 0, sizeof(stats)); + status = nrf_wifi_sys_fmac_stats_get(rpu_ctx_zep->rpu_ctx, + RPU_STATS_TYPE_ALL, + &stats); + if (status != NRF_WIFI_STATUS_SUCCESS) { + LOG_ERR("%s: Failed to get RPU stats", __func__); + goto ret; + } + + /* Treat stats.fw as a blob and divide into uint32_t chunks */ + fw_stats_size = sizeof(stats.fw); + num_uint32 = fw_stats_size / sizeof(uint32_t); + fw_stats_bytes = (const uint8_t *)&stats.fw; + + vendor_idx = 0; + + for (i = 0; i < num_uint32 && vendor_idx < MAX_VENDOR_STATS - 1; i++) { + uint32_t val; + const char **key_ptr; + uint32_t *val_ptr; + + /* Extract uint32_t value from blob */ + memcpy(&val, fw_stats_bytes + i * sizeof(uint32_t), sizeof(uint32_t)); + + /* Create key name */ + snprintk(vif_ctx_zep->vendor_key_strings[vendor_idx], 16, "fw_%zu", i); + + /* Assign key */ + key_ptr = (const char **) + &vif_ctx_zep->eth_stats_vendor_data[vendor_idx].key; + *key_ptr = vif_ctx_zep->vendor_key_strings[vendor_idx]; + + /* Assign value */ + val_ptr = (uint32_t *) + &vif_ctx_zep->eth_stats_vendor_data[vendor_idx].value; + *val_ptr = val; + + vendor_idx++; + } + + /* Null terminator entry */ + { + const char **key_ptr = (const char **) + &vif_ctx_zep->eth_stats_vendor_data[vendor_idx].key; + uint32_t *val_ptr = (uint32_t *) + &vif_ctx_zep->eth_stats_vendor_data[vendor_idx].value; + + *key_ptr = NULL; + *val_ptr = 0; + } + + /* Point to the static vendor data */ + vif_ctx_zep->eth_stats.vendor = vif_ctx_zep->eth_stats_vendor_data; + +ret: +#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */ return &vif_ctx_zep->eth_stats; out: return NULL; diff --git a/drivers/wifi/nrf_wifi/src/wifi_mgmt.c b/drivers/wifi/nrf_wifi/src/wifi_mgmt.c index e48ae31734a7..6bb31241b295 100644 --- a/drivers/wifi/nrf_wifi/src/wifi_mgmt.c +++ b/drivers/wifi/nrf_wifi/src/wifi_mgmt.c @@ -564,8 +564,9 @@ int nrf_wifi_set_twt(const struct device *dev, twt_info.dialog_token = twt_params->dialog_token; twt_info.twt_wake_ahead_duration = twt_params->setup.twt_wake_ahead_duration; +#ifndef CONFIG_NRF71_ON_IPC twt_info.twt_req_timeout = CONFIG_NRF_WIFI_TWT_SETUP_TIMEOUT_MS; - +#endif /* CONFIG_NRF71_ON_IPC */ status = nrf_wifi_sys_fmac_twt_setup(rpu_ctx_zep->rpu_ctx, vif_ctx_zep->vif_idx, &twt_info); diff --git a/drivers/wifi/nrf_wifi/src/wifi_util.c b/drivers/wifi/nrf_wifi/src/wifi_util.c index 57bda1f4ff4f..50c9e947229b 100644 --- a/drivers/wifi/nrf_wifi/src/wifi_util.c +++ b/drivers/wifi/nrf_wifi/src/wifi_util.c @@ -8,14 +8,20 @@ * @brief NRF Wi-Fi util shell module */ #include +#ifdef NRF71_ON_IPC +#include +#else #include "host_rpu_umac_if.h" +#endif #include "common/fmac_util.h" #include "system/fmac_api.h" #include "fmac_main.h" #include "wifi_util.h" +#ifndef CONFIG_NRF71_ON_IPC #include "rpu_lmac_phy_stats.h" #include "rpu_umac_stats.h" +#endif extern struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep; struct nrf_wifi_ctx_zep *ctx = &rpu_drv_priv_zep.rpu_ctx_zep; @@ -973,6 +979,7 @@ static int nrf_wifi_util_rpu_recovery_info(const struct shell *sh, } #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ +#ifndef CONFIG_NRF71_ON_IPC static int nrf_wifi_dump_stats(const struct shell *sh, struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, const char *name, @@ -1010,6 +1017,7 @@ static int nrf_wifi_dump_stats(const struct shell *sh, return ret; } + static int nrf_wifi_util_dump_rpu_stats_mem(const struct shell *sh, size_t argc, const char *argv[]) @@ -1095,6 +1103,7 @@ static int nrf_wifi_util_dump_rpu_stats_mem(const struct shell *sh, k_mutex_unlock(&ctx->rpu_lock); return ret; } +#endif /* !CONFIG_NRF71_ON_IPC */ SHELL_STATIC_SUBCMD_SET_CREATE( nrf70_util, @@ -1199,6 +1208,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE( 1, 0), #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ +#ifndef CONFIG_NRF71_ON_IPC SHELL_CMD_ARG(rpu_stats_mem, NULL, "Display RPU stats by reading from memory " @@ -1206,6 +1216,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE( nrf_wifi_util_dump_rpu_stats_mem, 1, 1), +#endif /* !CONFIG_NRF71_ON_IPC */ SHELL_SUBCMD_SET_END); diff --git a/drivers/wifi/nrf_wifi/src/wifi_util.h b/drivers/wifi/nrf_wifi/src/wifi_util.h index 303d5feac99f..a2490a1df24c 100644 --- a/drivers/wifi/nrf_wifi/src/wifi_util.h +++ b/drivers/wifi/nrf_wifi/src/wifi_util.h @@ -14,7 +14,11 @@ #include #include #include +#ifdef CONFIG_NRF71_ON_IPC +#include +#else #include +#endif #include #include diff --git a/drivers/wifi/nrf_wifi/src/wpa_supp_if.c b/drivers/wifi/nrf_wifi/src/wpa_supp_if.c index 9f1fff535454..88ea9f9215b4 100644 --- a/drivers/wifi/nrf_wifi/src/wpa_supp_if.c +++ b/drivers/wifi/nrf_wifi/src/wpa_supp_if.c @@ -447,7 +447,10 @@ void *nrf_wifi_wpa_supp_dev_init(void *supp_drv_if_ctx, const char *iface_name, struct zep_wpa_supp_dev_callbk_fns *supp_callbk_fns) { struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; - const struct device *device = DEVICE_DT_GET(DT_CHOSEN(zephyr_wifi)); + /* Get device for each interface */ + int if_idx = net_if_get_by_name(iface_name); + struct net_if *iface = net_if_get_by_index(if_idx); + const struct device *device = net_if_get_device(iface); if (!device) { LOG_ERR("%s: Interface %s not found", __func__, iface_name); diff --git a/dts/arm/nordic/nrf51822.dtsi b/dts/arm/nordic/nrf51822.dtsi index cbfef90faa5b..8f262909d61f 100644 --- a/dts/arm/nordic/nrf51822.dtsi +++ b/dts/arm/nordic/nrf51822.dtsi @@ -311,7 +311,6 @@ #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <1024>; diff --git a/dts/arm/nordic/nrf51822_qfaa.dtsi b/dts/arm/nordic/nrf51822_qfaa.dtsi index 07fc5dd1cce9..2aeec68fd852 100644 --- a/dts/arm/nordic/nrf51822_qfaa.dtsi +++ b/dts/arm/nordic/nrf51822_qfaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf51822-qfaa", "nordic,nrf51822", - "nordic,nrf51", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf51822_qfab.dtsi b/dts/arm/nordic/nrf51822_qfab.dtsi index 7fb4364d0379..6f6818ac4607 100644 --- a/dts/arm/nordic/nrf51822_qfab.dtsi +++ b/dts/arm/nordic/nrf51822_qfab.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf51822-qfab", "nordic,nrf51822", - "nordic,nrf51", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf51822_qfac.dtsi b/dts/arm/nordic/nrf51822_qfac.dtsi index 59a2ed265e67..eae879189c0c 100644 --- a/dts/arm/nordic/nrf51822_qfac.dtsi +++ b/dts/arm/nordic/nrf51822_qfac.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf51822-qfac", "nordic,nrf51822", - "nordic,nrf51", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52805.dtsi b/dts/arm/nordic/nrf52805.dtsi index 45a54f97b061..b686ddcabb02 100644 --- a/dts/arm/nordic/nrf52805.dtsi +++ b/dts/arm/nordic/nrf52805.dtsi @@ -11,7 +11,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -106,12 +106,13 @@ status = "okay"; ble-2mbps-supported; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; @@ -320,7 +321,6 @@ #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <4096>; diff --git a/dts/arm/nordic/nrf52805_caaa.dtsi b/dts/arm/nordic/nrf52805_caaa.dtsi index b7d24861893a..285d21440599 100644 --- a/dts/arm/nordic/nrf52805_caaa.dtsi +++ b/dts/arm/nordic/nrf52805_caaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf52805-caaa", "nordic,nrf52805", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52810.dtsi b/dts/arm/nordic/nrf52810.dtsi index 217758dd1614..7f4c1a7a5f5b 100644 --- a/dts/arm/nordic/nrf52810.dtsi +++ b/dts/arm/nordic/nrf52810.dtsi @@ -7,7 +7,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -110,12 +110,13 @@ status = "okay"; ble-2mbps-supported; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; @@ -180,6 +181,7 @@ #io-channel-cells = <1>; zephyr,pm-device-runtime-auto; }; + timer0: timer@40008000 { compatible = "nordic,nrf-timer"; status = "disabled"; @@ -345,7 +347,6 @@ #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <4096>; diff --git a/dts/arm/nordic/nrf52810_qfaa.dtsi b/dts/arm/nordic/nrf52810_qfaa.dtsi index 98fbd9a09369..bbc76ab75971 100644 --- a/dts/arm/nordic/nrf52810_qfaa.dtsi +++ b/dts/arm/nordic/nrf52810_qfaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf52810-qfaa", "nordic,nrf52810", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52811.dtsi b/dts/arm/nordic/nrf52811.dtsi index 670f569c0ace..8431bb9c2ce6 100644 --- a/dts/arm/nordic/nrf52811.dtsi +++ b/dts/arm/nordic/nrf52811.dtsi @@ -11,7 +11,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -122,12 +122,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; @@ -159,7 +160,7 @@ }; spi1: spi@40003000 { - /* cannot be used with i2c0 */ + /* cannot be used with i2c0 */ /* * This spi node can be SPI, SPIM, or SPIS, * for the user to pick: @@ -377,7 +378,6 @@ #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <4096>; diff --git a/dts/arm/nordic/nrf52811_qfaa.dtsi b/dts/arm/nordic/nrf52811_qfaa.dtsi index 3bb1556eadb7..17b387919dc8 100644 --- a/dts/arm/nordic/nrf52811_qfaa.dtsi +++ b/dts/arm/nordic/nrf52811_qfaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf52811-qfaa", "nordic,nrf52811", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index 50c8d2ba07f0..85aab283bfd2 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -9,9 +9,8 @@ #include / { - chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -124,12 +123,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK another Bluetooth controller - * is added and set as the default. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; @@ -389,7 +389,6 @@ #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <4096>; diff --git a/dts/arm/nordic/nrf52820_qdaa.dtsi b/dts/arm/nordic/nrf52820_qdaa.dtsi index c1d4a5a95f5a..a683ddcd2e61 100644 --- a/dts/arm/nordic/nrf52820_qdaa.dtsi +++ b/dts/arm/nordic/nrf52820_qdaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf52820-qdaa", "nordic,nrf52820", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52832.dtsi b/dts/arm/nordic/nrf52832.dtsi index 7bd62c707545..776397ff14a5 100644 --- a/dts/arm/nordic/nrf52832.dtsi +++ b/dts/arm/nordic/nrf52832.dtsi @@ -7,7 +7,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -110,12 +110,13 @@ status = "okay"; ble-2mbps-supported; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; @@ -412,7 +413,6 @@ #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <4096>; diff --git a/dts/arm/nordic/nrf52832_ciaa.dtsi b/dts/arm/nordic/nrf52832_ciaa.dtsi index 88f16574bbb9..81bed18daf27 100644 --- a/dts/arm/nordic/nrf52832_ciaa.dtsi +++ b/dts/arm/nordic/nrf52832_ciaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf52832-ciaa", "nordic,nrf52832", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52832_qfaa.dtsi b/dts/arm/nordic/nrf52832_qfaa.dtsi index 2943de6d1155..81bed18daf27 100644 --- a/dts/arm/nordic/nrf52832_qfaa.dtsi +++ b/dts/arm/nordic/nrf52832_qfaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf52832-qfaa", "nordic,nrf52832", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52832_qfab.dtsi b/dts/arm/nordic/nrf52832_qfab.dtsi index fe1605394e72..faecc765efdf 100644 --- a/dts/arm/nordic/nrf52832_qfab.dtsi +++ b/dts/arm/nordic/nrf52832_qfab.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf52832-qfab", "nordic,nrf52832", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52833.dtsi b/dts/arm/nordic/nrf52833.dtsi index 8202ddc45431..647f56c5aa42 100644 --- a/dts/arm/nordic/nrf52833.dtsi +++ b/dts/arm/nordic/nrf52833.dtsi @@ -11,7 +11,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -124,12 +124,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; @@ -434,7 +435,6 @@ #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <4096>; diff --git a/dts/arm/nordic/nrf52833_qdaa.dtsi b/dts/arm/nordic/nrf52833_qdaa.dtsi index 7f9be6f22550..64462d29269b 100644 --- a/dts/arm/nordic/nrf52833_qdaa.dtsi +++ b/dts/arm/nordic/nrf52833_qdaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf52833-qdaa", "nordic,nrf52833", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52833_qiaa.dtsi b/dts/arm/nordic/nrf52833_qiaa.dtsi index 68eabb08bcf7..6ab9a4f1e6eb 100644 --- a/dts/arm/nordic/nrf52833_qiaa.dtsi +++ b/dts/arm/nordic/nrf52833_qiaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf52833-qiaa", "nordic,nrf52833", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index dab5f7620585..9d7027744bef 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -7,8 +7,8 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; - zephyr,entropy = &rng; + zephyr,bt-hci = &bt_hci_sdc; + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; @@ -112,12 +112,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; @@ -421,7 +422,6 @@ #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <4096>; @@ -572,7 +572,7 @@ reg = <0x5002a000 0x1000>, <0x5002b000 0x1000>; reg-names = "wrapper", "core"; interrupts = <42 NRF_DEFAULT_IRQ_PRIORITY>; - status = "disabled"; + status = "okay"; }; }; }; diff --git a/dts/arm/nordic/nrf52840_qfaa.dtsi b/dts/arm/nordic/nrf52840_qfaa.dtsi index 8c927eb5c0a6..6d549a45d1dd 100644 --- a/dts/arm/nordic/nrf52840_qfaa.dtsi +++ b/dts/arm/nordic/nrf52840_qfaa.dtsi @@ -17,10 +17,8 @@ / { soc { - compatible = "nordic,nrf52840-qfaa", "nordic,nrf52840", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; - }; /delete-node/ &usbd; diff --git a/dts/arm/nordic/nrf52840_qiaa.dtsi b/dts/arm/nordic/nrf52840_qiaa.dtsi index 657222447193..7986ab41fd6a 100644 --- a/dts/arm/nordic/nrf52840_qiaa.dtsi +++ b/dts/arm/nordic/nrf52840_qiaa.dtsi @@ -26,7 +26,6 @@ / { soc { - compatible = "nordic,nrf52840-qiaa", "nordic,nrf52840", - "nordic,nrf52", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf5340_cpuapp.dtsi b/dts/arm/nordic/nrf5340_cpuapp.dtsi index b9762248a5df..b4c077ea2bf4 100644 --- a/dts/arm/nordic/nrf5340_cpuapp.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp.dtsi @@ -34,7 +34,7 @@ }; chosen { - zephyr,entropy = &rng_hci; + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; @@ -104,7 +104,7 @@ reg = <0x50844000 0x1000>, <0x50845000 0x1000>; reg-names = "wrapper", "core"; interrupts = <68 NRF_DEFAULT_IRQ_PRIORITY>; - status = "disabled"; + status = "okay"; }; }; diff --git a/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi b/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi index 7021b7eedeb1..ea56b3206bcc 100644 --- a/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi @@ -536,7 +536,6 @@ flash_controller: flash-controller@39000 { #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <4096>; diff --git a/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi b/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi index a543ffe906b1..76a2af386623 100644 --- a/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf5340-cpuapp-qkaa", "nordic,nrf5340-cpuapp", - "nordic,nrf53", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf5340_cpuappns_qkaa.dtsi b/dts/arm/nordic/nrf5340_cpuappns_qkaa.dtsi index 80d5706232f6..37d6a605556e 100644 --- a/dts/arm/nordic/nrf5340_cpuappns_qkaa.dtsi +++ b/dts/arm/nordic/nrf5340_cpuappns_qkaa.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf5340-cpuapp-qkaa", "nordic,nrf5340-cpuapp", - "nordic,nrf53", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf5340_cpunet.dtsi b/dts/arm/nordic/nrf5340_cpunet.dtsi index 4f9164767f1a..e80399b5770a 100644 --- a/dts/arm/nordic/nrf5340_cpunet.dtsi +++ b/dts/arm/nordic/nrf5340_cpunet.dtsi @@ -9,7 +9,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -102,12 +102,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; @@ -309,7 +310,6 @@ #address-cells = <1>; #size-cells = <1>; - flash1: flash@1000000 { compatible = "soc-nv-flash"; erase-block-size = <2048>; diff --git a/dts/arm/nordic/nrf5340_cpunet_qkaa.dtsi b/dts/arm/nordic/nrf5340_cpunet_qkaa.dtsi index 19eb682ddfc6..e9948125ba89 100644 --- a/dts/arm/nordic/nrf5340_cpunet_qkaa.dtsi +++ b/dts/arm/nordic/nrf5340_cpunet_qkaa.dtsi @@ -21,7 +21,6 @@ / { soc { - compatible = "nordic,nrf5340-cpunet-qkaa", "nordic,nrf5340-cpunet", - "nordic,nrf53", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf54h20_cpuapp.dtsi b/dts/arm/nordic/nrf54h20_cpuapp.dtsi index 9e790656e501..88ace7842aa3 100644 --- a/dts/arm/nordic/nrf54h20_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54h20_cpuapp.dtsi @@ -7,12 +7,19 @@ #include cpu: &cpuapp {}; + systick: &cpuapp_systick {}; + nvic: &cpuapp_nvic {}; + cpuppr_vevif: &cpuppr_vevif_tx {}; + cpuflpr_vevif: &cpuflpr_vevif_tx {}; + cpusys_vevif: &cpusys_vevif_tx {}; + wdt010: &cpuapp_wdt010 {}; + wdt011: &cpuapp_wdt011 {}; /delete-node/ &cpuppr; @@ -60,18 +67,6 @@ wdt011: &cpuapp_wdt011 {}; interrupts = <109 NRF_DEFAULT_IRQ_PRIORITY>; }; -&fll16m { - status = "okay"; -}; - -&hsfll120 { - status = "okay"; -}; - -&lfclk { - status = "okay"; -}; - &gdpwr { status = "okay"; }; @@ -95,27 +90,3 @@ wdt011: &cpuapp_wdt011 {}; &gdpwr_slow_main { status = "okay"; }; - -&gpio_pad_group0 { - status = "okay"; -}; - -&gpio_pad_group1 { - status = "okay"; -}; - -&gpio_pad_group2 { - status = "okay"; -}; - -&gpio_pad_group6 { - status = "okay"; -}; - -&gpio_pad_group7 { - status = "okay"; -}; - -&gpio_pad_group9 { - status = "okay"; -}; diff --git a/dts/arm/nordic/nrf54h20_cpurad.dtsi b/dts/arm/nordic/nrf54h20_cpurad.dtsi index 279bc7581112..2cde225beb01 100644 --- a/dts/arm/nordic/nrf54h20_cpurad.dtsi +++ b/dts/arm/nordic/nrf54h20_cpurad.dtsi @@ -7,12 +7,19 @@ #include cpu: &cpurad {}; + systick: &cpurad_systick {}; + nvic: &cpurad_nvic {}; + cpuppr_vevif: &cpuppr_vevif_tx {}; + cpuflpr_vevif: &cpuflpr_vevif_tx {}; + cpusys_vevif: &cpusys_vevif_tx {}; + wdt010: &cpurad_wdt010 {}; + wdt011: &cpurad_wdt011 {}; /delete-node/ &cpuapp; @@ -21,8 +28,13 @@ wdt011: &cpurad_wdt011 {}; /delete-node/ &cpuapp_ram0; /delete-node/ &cpuppr; /delete-node/ &cpuflpr; +/delete-node/ &s2ram; / { + chosen { + zephyr,bt-hci = &bt_hci_sdc; + }; + soc { compatible = "simple-bus"; interrupt-parent = <&cpurad_nvic>; @@ -100,18 +112,6 @@ wdt011: &cpurad_wdt011 {}; status = "okay"; }; -&fll16m { - status = "okay"; -}; - -&hsfll120 { - status = "okay"; -}; - -&lfclk { - status = "okay"; -}; - &gdpwr { status = "okay"; }; @@ -136,26 +136,6 @@ wdt011: &cpurad_wdt011 {}; status = "okay"; }; -&gpio_pad_group0 { - status = "okay"; -}; - -&gpio_pad_group1 { - status = "okay"; -}; - -&gpio_pad_group2 { - status = "okay"; -}; - -&gpio_pad_group6 { - status = "okay"; -}; - -&gpio_pad_group7 { - status = "okay"; -}; - -&gpio_pad_group9 { +&bt_hci_sdc { status = "okay"; }; diff --git a/dts/arm/nordic/nrf54l_05_10_15_cpuapp.dtsi b/dts/arm/nordic/nrf54l_05_10_15_cpuapp.dtsi index 3f1fe655b6e5..f4c673b1f516 100644 --- a/dts/arm/nordic/nrf54l_05_10_15_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54l_05_10_15_cpuapp.dtsi @@ -5,7 +5,9 @@ */ cpu: &cpuapp {}; + systick: &cpuapp_systick {}; + nvic: &cpuapp_nvic {}; /delete-node/ &cpuflpr; @@ -15,8 +17,8 @@ nvic: &cpuapp_nvic {}; / { chosen { - zephyr,bt-hci = &bt_hci_controller; - zephyr,entropy = &rng; + zephyr,bt-hci = &bt_hci_sdc; + zephyr,entropy = &psa_rng; }; soc { @@ -26,17 +28,17 @@ nvic: &cpuapp_nvic {}; }; rng: rng { - status = "okay"; + status = "disabled"; compatible = "nordic,nrf-cracen-ctrdrbg"; }; psa_rng: psa-rng { compatible = "zephyr,psa-crypto-rng"; - status = "disabled"; + status = "okay"; }; }; -&bt_hci_controller { +&bt_hci_sdc { status = "okay"; }; @@ -72,7 +74,7 @@ nvic: &cpuapp_nvic {}; #else interrupts = <228 NRF_DEFAULT_IRQ_PRIORITY>, #endif - <229 NRF_DEFAULT_IRQ_PRIORITY>; /* reserved for Zero Latency IRQs */ + <229 NRF_DEFAULT_IRQ_PRIORITY>; /* reserved for Zero Latency IRQs */ }; &gpiote20 { diff --git a/dts/arm/nordic/nrf54lm20a_enga_cpuapp.dtsi b/dts/arm/nordic/nrf54lm20a_enga_cpuapp.dtsi index dc13fb40d6aa..8c8d006e1a18 100644 --- a/dts/arm/nordic/nrf54lm20a_enga_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54lm20a_enga_cpuapp.dtsi @@ -7,7 +7,9 @@ #include cpu: &cpuapp {}; + systick: &cpuapp_systick {}; + nvic: &cpuapp_nvic {}; /delete-node/ &cpuflpr; @@ -17,7 +19,8 @@ nvic: &cpuapp_nvic {}; / { chosen { - zephyr,entropy = &rng; + zephyr,bt-hci = &bt_hci_sdc; + zephyr,entropy = &psa_rng; }; soc { @@ -28,15 +31,19 @@ nvic: &cpuapp_nvic {}; psa_rng: psa-rng { compatible = "zephyr,psa-crypto-rng"; - status = "disabled"; + status = "okay"; }; rng: rng { - status = "okay"; + status = "disabled"; compatible = "nordic,nrf-cracen-ctrdrbg"; }; }; +&bt_hci_sdc { + status = "okay"; +}; + &cpuflpr_vpr { cpuapp_vevif_rx: mailbox@1 { compatible = "nordic,nrf-vevif-event-rx"; @@ -64,16 +71,28 @@ nvic: &cpuapp_nvic {}; }; &grtc { +#ifdef USE_NON_SECURE_ADDRESS_MAP + interrupts = <227 NRF_DEFAULT_IRQ_PRIORITY>, +#else interrupts = <228 NRF_DEFAULT_IRQ_PRIORITY>, +#endif <229 NRF_DEFAULT_IRQ_PRIORITY>; /* reserved for Zero Latency IRQs */ }; &gpiote20 { +#ifdef USE_NON_SECURE_ADDRESS_MAP + interrupts = <218 NRF_DEFAULT_IRQ_PRIORITY>; +#else interrupts = <219 NRF_DEFAULT_IRQ_PRIORITY>; +#endif }; &gpiote30 { +#ifdef USE_NON_SECURE_ADDRESS_MAP + interrupts = <268 NRF_DEFAULT_IRQ_PRIORITY>; +#else interrupts = <269 NRF_DEFAULT_IRQ_PRIORITY>; +#endif }; &dppic00 { diff --git a/dts/arm/nordic/nrf91.dtsi b/dts/arm/nordic/nrf91.dtsi index 1747dcea74a9..31cbe7d9ea41 100644 --- a/dts/arm/nordic/nrf91.dtsi +++ b/dts/arm/nordic/nrf91.dtsi @@ -28,6 +28,7 @@ }; chosen { + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; @@ -51,7 +52,7 @@ reg = <0x50840000 0x1000>, <0x50841000 0x1000>; reg-names = "wrapper", "core"; interrupts = <64 NRF_DEFAULT_IRQ_PRIORITY>; - status = "disabled"; + status = "okay"; }; ctrlap: ctrlap@50006000 { @@ -65,7 +66,7 @@ * so we give it the 'gpiote' label for use when building * code for this target. */ - gpiote: gpiote0: gpiote@5000d000 { + gpiote: gpiote0: gpiote@5000d000 { compatible = "nordic,nrf-gpiote"; reg = <0x5000d000 0x1000>; interrupts = <13 5>; diff --git a/dts/arm/nordic/nrf9131_laca.dtsi b/dts/arm/nordic/nrf9131_laca.dtsi index f32f0c825ad1..77fe73c22af6 100644 --- a/dts/arm/nordic/nrf9131_laca.dtsi +++ b/dts/arm/nordic/nrf9131_laca.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf9131-laca", "nordic,nrf9120", - "nordic,nrf91", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9131ns_laca.dtsi b/dts/arm/nordic/nrf9131ns_laca.dtsi index 3b6208f45e91..6ab80a842a33 100644 --- a/dts/arm/nordic/nrf9131ns_laca.dtsi +++ b/dts/arm/nordic/nrf9131ns_laca.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf9131-laca", "nordic,nrf9120", - "nordic,nrf91", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9151_laca.dtsi b/dts/arm/nordic/nrf9151_laca.dtsi index 9ed202740170..77fe73c22af6 100644 --- a/dts/arm/nordic/nrf9151_laca.dtsi +++ b/dts/arm/nordic/nrf9151_laca.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf9151-laca", "nordic,nrf9120", - "nordic,nrf91", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9151ns_laca.dtsi b/dts/arm/nordic/nrf9151ns_laca.dtsi index ac31c6e19c60..6ab80a842a33 100644 --- a/dts/arm/nordic/nrf9151ns_laca.dtsi +++ b/dts/arm/nordic/nrf9151ns_laca.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf9151-laca", "nordic,nrf9120", - "nordic,nrf91", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9160_sica.dtsi b/dts/arm/nordic/nrf9160_sica.dtsi index 15096534016d..6bbe048277c1 100644 --- a/dts/arm/nordic/nrf9160_sica.dtsi +++ b/dts/arm/nordic/nrf9160_sica.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf9160-sica", "nordic,nrf9160", - "nordic,nrf91", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9160ns_sica.dtsi b/dts/arm/nordic/nrf9160ns_sica.dtsi index c6adbaa7ca2f..12ec1fcbc8e0 100644 --- a/dts/arm/nordic/nrf9160ns_sica.dtsi +++ b/dts/arm/nordic/nrf9160ns_sica.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf9160-sica", "nordic,nrf9160", - "nordic,nrf91", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9161_laca.dtsi b/dts/arm/nordic/nrf9161_laca.dtsi index e94ab99166a0..77fe73c22af6 100644 --- a/dts/arm/nordic/nrf9161_laca.dtsi +++ b/dts/arm/nordic/nrf9161_laca.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf9161-laca", "nordic,nrf9120", - "nordic,nrf91", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9161ns_laca.dtsi b/dts/arm/nordic/nrf9161ns_laca.dtsi index 4449c3565b32..6ab80a842a33 100644 --- a/dts/arm/nordic/nrf9161ns_laca.dtsi +++ b/dts/arm/nordic/nrf9161ns_laca.dtsi @@ -17,7 +17,6 @@ / { soc { - compatible = "nordic,nrf9161-laca", "nordic,nrf9120", - "nordic,nrf91", "simple-bus"; + compatible = "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf91_peripherals.dtsi b/dts/arm/nordic/nrf91_peripherals.dtsi index 476f8415853a..3e7e42472b9b 100644 --- a/dts/arm/nordic/nrf91_peripherals.dtsi +++ b/dts/arm/nordic/nrf91_peripherals.dtsi @@ -12,7 +12,6 @@ flash_controller: flash-controller@39000 { #address-cells = <1>; #size-cells = <1>; - flash0: flash@0 { compatible = "soc-nv-flash"; erase-block-size = <4096>; diff --git a/dts/arm/nordic/nrf9280_cpuapp.dtsi b/dts/arm/nordic/nrf9280_cpuapp.dtsi index 29edae31051d..01716a656785 100644 --- a/dts/arm/nordic/nrf9280_cpuapp.dtsi +++ b/dts/arm/nordic/nrf9280_cpuapp.dtsi @@ -7,11 +7,17 @@ #include cpu: &cpuapp {}; + systick: &cpuapp_systick {}; + nvic: &cpuapp_nvic {}; + cpuppr_vevif: &cpuppr_vevif_tx {}; + cpusys_vevif: &cpusys_vevif_tx {}; + wdt010: &cpuapp_wdt010 {}; + wdt011: &cpuapp_wdt011 {}; /delete-node/ &cpuppr; diff --git a/dts/arm/nordic/nrf9280_cpurad.dtsi b/dts/arm/nordic/nrf9280_cpurad.dtsi index 265cd6239537..9a88533507f3 100644 --- a/dts/arm/nordic/nrf9280_cpurad.dtsi +++ b/dts/arm/nordic/nrf9280_cpurad.dtsi @@ -7,11 +7,17 @@ #include cpu: &cpurad {}; + systick: &cpurad_systick {}; + nvic: &cpurad_nvic {}; + cpuppr_vevif: &cpuppr_vevif_tx {}; + cpusys_vevif: &cpusys_vevif_tx {}; + wdt010: &cpurad_wdt010 {}; + wdt011: &cpurad_wdt011 {}; /delete-node/ &cpuapp; diff --git a/dts/arm/silabs/siwg917.dtsi b/dts/arm/silabs/siwg917.dtsi index ceb79d35152c..9cc9f358f048 100644 --- a/dts/arm/silabs/siwg917.dtsi +++ b/dts/arm/silabs/siwg917.dtsi @@ -124,6 +124,13 @@ status = "disabled"; }; + siwx91x_soc_pd: siwx91x-soc-pd { + compatible = "silabs,siwx91x-power-domain"; + #power-domain-cells = <0>; + zephyr,pm-device-runtime-auto; + status = "okay"; + }; + ulpuart: uart@24041800 { compatible = "ns16550"; reg = <0x24041800 0x1000>; @@ -131,6 +138,8 @@ reg-shift = <2>; clocks = <&clock0 SIWX91X_CLK_ULP_UART>; current-speed = <115200>; + power-domains = <&siwx91x_soc_pd>; + zephyr,pm-device-runtime-auto; status = "disabled"; }; @@ -141,6 +150,8 @@ reg-shift = <2>; clocks = <&clock0 SIWX91X_CLK_UART0>; current-speed = <115200>; + power-domains = <&siwx91x_soc_pd>; + zephyr,pm-device-runtime-auto; status = "disabled"; }; @@ -151,6 +162,8 @@ reg-shift = <2>; clocks = <&clock0 SIWX91X_CLK_UART1>; current-speed = <115200>; + power-domains = <&siwx91x_soc_pd>; + zephyr,pm-device-runtime-auto; status = "disabled"; }; diff --git a/dts/bindings/arm/nordic,nrf-tddconf.yaml b/dts/bindings/arm/nordic,nrf-tddconf.yaml deleted file mode 100644 index 2273082c12f9..000000000000 --- a/dts/bindings/arm/nordic,nrf-tddconf.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -description: | - Nordic TRACE and Debug Domain - - Configuration for the Trace and Debug subsystem - -compatible: "nordic,nrf-tddconf" - -include: base.yaml - -properties: - etbsources: - type: int - description: | - Bitmask of enabled sources for the ETB sink. Valid values can be found in - dt-bindings/misc/nordic-tddconf.h - - tpiusources: - type: int - description: | - Bitmask of enabled sources for the TPIU sink. Valid values can be found in - dt-bindings/misc/nordic-tddconf.h - - etrsources: - type: int - description: | - Bitmask of enabled sources for the ETR sink. Valid values can be found in - dt-bindings/misc/nordic-tddconf.h - - portconfig: - type: int - default: 3 - description: TPIU clock divider - TDD HSFLL / 2^(2 + portconfig) - enum: - - 0 - - 1 - - 2 - - 3 - - etrbuffer: - description: phandle to the memory region used for the ETR buffer - type: phandle diff --git a/dts/bindings/comparator/nordic,nrf-comp.yaml b/dts/bindings/comparator/nordic,nrf-comp.yaml index e4f6838d2049..f1405a6de2c9 100644 --- a/dts/bindings/comparator/nordic,nrf-comp.yaml +++ b/dts/bindings/comparator/nordic,nrf-comp.yaml @@ -25,7 +25,7 @@ description: | &comp { status = "okay"; main-mode = "SE"; - psel = "AIN0"; + psel = ; refsel = "INT_1V2"; sp-mode = "NORMAL"; th-up = <36>; @@ -39,7 +39,7 @@ description: | &comp { ... refsel = "AREF"; - extrefsel = "AIN1"; + extrefsel = ; ... }; @@ -49,8 +49,8 @@ description: | &comp { status = "okay"; main-mode = "DIFF"; - psel = "AIN0"; - extrefsel = "AIN1"; + psel = ; + extrefsel = ; sp-mode = "NORMAL"; enable-hyst; isource = "DISABLED"; @@ -68,30 +68,10 @@ properties: - "DIFF" psel: - type: string - enum: - - "AIN0" - - "AIN1" - - "AIN2" - - "AIN3" - - "AIN4" - - "AIN5" - - "AIN6" - - "AIN7" - - "VDD_DIV2" - - "VDDH_DIV5" + type: int extrefsel: - type: string - enum: - - "AIN0" - - "AIN1" - - "AIN2" - - "AIN3" - - "AIN4" - - "AIN5" - - "AIN6" - - "AIN7" + type: int refsel: type: string diff --git a/dts/bindings/comparator/nordic,nrf-lpcomp.yaml b/dts/bindings/comparator/nordic,nrf-lpcomp.yaml index 64a30b330d8b..4995155ed76b 100644 --- a/dts/bindings/comparator/nordic,nrf-lpcomp.yaml +++ b/dts/bindings/comparator/nordic,nrf-lpcomp.yaml @@ -21,7 +21,7 @@ description: | &comp { status = "okay"; - psel = "AIN0"; + psel = ; refsel = "VDD_4_8"; enable-hyst; }; @@ -32,7 +32,7 @@ description: | &comp { ... refsel = "AREF"; - extrefsel = "AIN1"; + extrefsel = ; ... }; @@ -42,22 +42,10 @@ include: base.yaml properties: psel: - type: string - enum: - - "AIN0" - - "AIN1" - - "AIN2" - - "AIN3" - - "AIN4" - - "AIN5" - - "AIN6" - - "AIN7" + type: int extrefsel: - type: string - enum: - - "AIN0" - - "AIN1" + type: int refsel: type: string diff --git a/dts/bindings/debug/nordic,coresight-nrf.yaml b/dts/bindings/debug/nordic,coresight-nrf.yaml new file mode 100644 index 000000000000..fec4f37ce5a9 --- /dev/null +++ b/dts/bindings/debug/nordic,coresight-nrf.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic Coresight Subsystem (Trace Port Interface Unit) + +compatible: "nordic,coresight-nrf" + +include: [base.yaml, pinctrl-device.yaml, nordic-clockpin.yaml] + +properties: + reg: + required: true + + mode: + required: true + type: string + enum: + - "unconfigured" + - "stm-tpiu" + - "stm-etr" + description: > + Specifies which mode to configure the Coresight subsystem in. diff --git a/dts/bindings/misc/nordic,nrf-tbm.yaml b/dts/bindings/debug/nordic,nrf-tbm.yaml similarity index 100% rename from dts/bindings/misc/nordic,nrf-tbm.yaml rename to dts/bindings/debug/nordic,nrf-tbm.yaml diff --git a/dts/bindings/gpio/nordic,nrf-gpio-pad-group.yaml b/dts/bindings/gpio/nordic,nrf-gpio-pad-group.yaml deleted file mode 100644 index 104277addd35..000000000000 --- a/dts/bindings/gpio/nordic,nrf-gpio-pad-group.yaml +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2025 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -description: | - Nordic nRF GPIO pad group. - - The GPIO pad group describes the pads (package - pins of the SoC) the GPIO controller manages. - - The pads may be in a different power domain than - the GPIO controller, and may require enabling - retention to preserve the GPIO configuration if - the power domain is suspended. - - The GPIO pad group is a child node of the GPIO - controller which manages the pad group, named - pad-group. The pad group's nodelabel is named - gpio_pad_group. - - Example layout: - - gpio0: gpio@938000 { - compatible = "nordic,nrf-gpio"; - - ... - - gpio_pad_group0: pad-group { - compatible = "nordic,nrf-gpio-pad-group"; - power-domains = <&gdpwr_slow_main>; - retain-mask = <0xFFF>; - }; - }; - -compatible: "nordic,nrf-gpio-pad-group" - -include: base.yaml - -properties: - retain-mask: - type: int - description: | - Mask of pins which shall be retained if pad - group's power domain is powered off. diff --git a/dts/bindings/modem/nordic,nrf91-slm.yaml b/dts/bindings/modem/nordic,nrf91-slm.yaml index 3f06696197d2..11bf39018696 100644 --- a/dts/bindings/modem/nordic,nrf91-slm.yaml +++ b/dts/bindings/modem/nordic,nrf91-slm.yaml @@ -2,8 +2,4 @@ description: Nordic nRF91 series running the Serial LTE Modem application compatible: "nordic,nrf91-slm" -include: uart-device.yaml - -properties: - mdm-power-gpios: - type: phandle-array +include: zephyr,cellular-modem-device.yaml diff --git a/dts/bindings/modem/quectel,bg95.yaml b/dts/bindings/modem/quectel,bg95.yaml index 9b1f6c734be4..940cd41ea27e 100644 --- a/dts/bindings/modem/quectel,bg95.yaml +++ b/dts/bindings/modem/quectel,bg95.yaml @@ -5,7 +5,7 @@ description: Quectel BG95 modem compatible: "quectel,bg95" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-power-gpios: diff --git a/dts/bindings/modem/quectel,bg9x.yaml b/dts/bindings/modem/quectel,bg9x.yaml index 836df0ba36e5..41f32d0d4c26 100644 --- a/dts/bindings/modem/quectel,bg9x.yaml +++ b/dts/bindings/modem/quectel,bg9x.yaml @@ -5,16 +5,13 @@ description: quectel BG9x modem compatible: "quectel,bg9x" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-power-gpios: type: phandle-array required: true - mdm-reset-gpios: - type: phandle-array - mdm-dtr-gpios: type: phandle-array diff --git a/dts/bindings/modem/quectel,eg25-g.yaml b/dts/bindings/modem/quectel,eg25-g.yaml index 45284ddf174b..2e688e587dea 100644 --- a/dts/bindings/modem/quectel,eg25-g.yaml +++ b/dts/bindings/modem/quectel,eg25-g.yaml @@ -2,7 +2,7 @@ description: Quectel EG25-G modem compatible: "quectel,eg25-g" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-reset-gpios: diff --git a/dts/bindings/modem/quectel,eg800q.yaml b/dts/bindings/modem/quectel,eg800q.yaml index 80c591b90350..6b86456bcc91 100644 --- a/dts/bindings/modem/quectel,eg800q.yaml +++ b/dts/bindings/modem/quectel,eg800q.yaml @@ -2,7 +2,7 @@ description: Quectel EG800Q modem compatible: "quectel,eg800q" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-power-gpios: diff --git a/dts/bindings/modem/simcom,a76xx.yaml b/dts/bindings/modem/simcom,a76xx.yaml index 586b356de474..428977b42a13 100644 --- a/dts/bindings/modem/simcom,a76xx.yaml +++ b/dts/bindings/modem/simcom,a76xx.yaml @@ -5,7 +5,7 @@ description: Simcom A76XX modem compatible: "simcom,a76xx" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-power-gpios: diff --git a/dts/bindings/modem/simcom,sim7080.yaml b/dts/bindings/modem/simcom,sim7080.yaml index 952ce6b514b6..deb5a0ec4dd6 100644 --- a/dts/bindings/modem/simcom,sim7080.yaml +++ b/dts/bindings/modem/simcom,sim7080.yaml @@ -5,7 +5,7 @@ description: Simcom Sim7080 modem compatible: "simcom,sim7080" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-power-gpios: diff --git a/dts/bindings/modem/sqn,gm02s.yaml b/dts/bindings/modem/sqn,gm02s.yaml index 584fc878e18d..4875f6dcc471 100644 --- a/dts/bindings/modem/sqn,gm02s.yaml +++ b/dts/bindings/modem/sqn,gm02s.yaml @@ -5,12 +5,9 @@ description: Sequans Monarch 2 GM02S Modem compatible: "sqn,gm02s" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-reset-gpios: type: phandle-array required: true - - mdm-wake-gpios: - type: phandle-array diff --git a/dts/bindings/modem/swir,hl7800.yaml b/dts/bindings/modem/swir,hl7800.yaml index b937031455ff..3daf4b383d38 100644 --- a/dts/bindings/modem/swir,hl7800.yaml +++ b/dts/bindings/modem/swir,hl7800.yaml @@ -8,7 +8,7 @@ description: Sierra Wireless HL7800 Modem compatible: "swir,hl7800" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-wake-gpios: diff --git a/dts/bindings/modem/telit,me310g1.yaml b/dts/bindings/modem/telit,me310g1.yaml index 2ee36fce5958..ff354dcc2951 100644 --- a/dts/bindings/modem/telit,me310g1.yaml +++ b/dts/bindings/modem/telit,me310g1.yaml @@ -2,7 +2,7 @@ description: Telit ME310G1 Modem compatible: "telit,me310g1" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-power-gpios: diff --git a/dts/bindings/modem/telit,me910g1.yaml b/dts/bindings/modem/telit,me910g1.yaml index 2599b6cd237d..5ffa10af0347 100644 --- a/dts/bindings/modem/telit,me910g1.yaml +++ b/dts/bindings/modem/telit,me910g1.yaml @@ -5,7 +5,7 @@ description: Telit ME910G1 Modem compatible: "telit,me910g1" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-power-gpios: diff --git a/dts/bindings/modem/u-blox,lara-r6.yaml b/dts/bindings/modem/u-blox,lara-r6.yaml index 89e02d86dba1..12c802391e6b 100644 --- a/dts/bindings/modem/u-blox,lara-r6.yaml +++ b/dts/bindings/modem/u-blox,lara-r6.yaml @@ -5,12 +5,9 @@ description: u-blox LARA-R6 modem compatible: "u-blox,lara-r6" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-power-gpios: type: phandle-array required: true - - mdm-reset-gpios: - type: phandle-array diff --git a/dts/bindings/modem/u-blox,sara-r4.yaml b/dts/bindings/modem/u-blox,sara-r4.yaml index f24bc57e0a74..c9ec63dc7381 100644 --- a/dts/bindings/modem/u-blox,sara-r4.yaml +++ b/dts/bindings/modem/u-blox,sara-r4.yaml @@ -5,15 +5,12 @@ description: u-blox SARA-R4 modem compatible: "u-blox,sara-r4" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-power-gpios: type: phandle-array required: true - mdm-reset-gpios: - type: phandle-array - mdm-vint-gpios: type: phandle-array diff --git a/dts/bindings/modem/u-blox,sara-r5.yaml b/dts/bindings/modem/u-blox,sara-r5.yaml index af6c3318fd07..40e846fd4eae 100644 --- a/dts/bindings/modem/u-blox,sara-r5.yaml +++ b/dts/bindings/modem/u-blox,sara-r5.yaml @@ -5,11 +5,4 @@ description: u-blox SARA-R5 modem compatible: "u-blox,sara-r5" -include: uart-device.yaml - -properties: - mdm-power-gpios: - type: phandle-array - - mdm-reset-gpios: - type: phandle-array +include: zephyr,cellular-modem-device.yaml diff --git a/dts/bindings/modem/wnc,m14a2a.yaml b/dts/bindings/modem/wnc,m14a2a.yaml index db00b6fbeb64..71f9d2775938 100644 --- a/dts/bindings/modem/wnc,m14a2a.yaml +++ b/dts/bindings/modem/wnc,m14a2a.yaml @@ -5,7 +5,7 @@ description: WNC-M14A2A LTE-M modem compatible: "wnc,m14a2a" -include: uart-device.yaml +include: zephyr,cellular-modem-device.yaml properties: mdm-boot-mode-sel-gpios: diff --git a/dts/bindings/modem/zephyr,cellular-modem-device.yaml b/dts/bindings/modem/zephyr,cellular-modem-device.yaml new file mode 100644 index 000000000000..d2ab0056841b --- /dev/null +++ b/dts/bindings/modem/zephyr,cellular-modem-device.yaml @@ -0,0 +1,50 @@ +# Copyright 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Common properties for Zephyr cellular modems + +include: uart-device.yaml + +properties: + mdm-power-gpios: + type: phandle-array + description: GPIO for modem power control + + mdm-reset-gpios: + type: phandle-array + description: GPIO for modem reset + + mdm-wake-gpios: + type: phandle-array + description: GPIO for modem wake + + mdm-ring-gpios: + type: phandle-array + description: GPIO for modem ring indicator + + mdm-dtr-gpios: + type: phandle-array + description: | + GPIO for modem data terminal ready. + + Asserted (logical high) when UART is active and + deasserted (logical low) when UART is inactive, powered down or in low power mode. + + cmux-enable-runtime-power-save: + type: boolean + description: | + Enable runtime power saving using CMUX PSC commands. + This requires modem to support CMUX and PSC commands while keeping the data + connection active. + + cmux-close-pipe-on-power-save: + type: boolean + description: | + Close the modem pipe when entering power save mode. + When runtime power management is enabled, this closes the UART. + This requires modem to support waking up the UART using RING signal. + + cmux-idle-timeout-ms: + type: int + description: Time in milliseconds after which CMUX will enter power save mode. + default: 10000 diff --git a/dts/bindings/mspi/mspi-controller.yaml b/dts/bindings/mspi/mspi-controller.yaml index 0f574c12153e..dd7c99e34ece 100644 --- a/dts/bindings/mspi/mspi-controller.yaml +++ b/dts/bindings/mspi/mspi-controller.yaml @@ -22,8 +22,8 @@ properties: op-mode: type: string enum: - - "MSPI_CONTROLLER" - - "MSPI_PERIPHERAL" + - "MSPI_OP_MODE_CONTROLLER" + - "MSPI_OP_MODE_PERIPHERAL" description: | Indicate MSPI controller or peripheral mode of the controller. The controller driver may use this during initialization. @@ -92,3 +92,11 @@ properties: Regardless of whether the CE pin may need software control or MSPI controller has dedicated CE pin, this field should be defined to help manage multiple devices on the same MSPI controller. + + packet-data-limit: + type: int + description: | + Specifies the maximum length of data that the controller can transfer + in a single packet. Transceive requests made to the controller must be + split into multiple packets if a single one would exceed this value. + If not specified, no limit is imposed. diff --git a/dts/bindings/mspi/nordic,nrf-exmif.yaml b/dts/bindings/mspi/nordic,nrf-exmif.yaml index 294254aa60ef..4e46e5d6b142 100644 --- a/dts/bindings/mspi/nordic,nrf-exmif.yaml +++ b/dts/bindings/mspi/nordic,nrf-exmif.yaml @@ -6,3 +6,7 @@ description: Nordic External Memory Interface (EXMIF) compatible: "nordic,nrf-exmif" include: snps,designware-ssi.yaml + +properties: + op-mode: + default: "MSPI_OP_MODE_CONTROLLER" diff --git a/dts/bindings/mspi/nordic,nrf-qspi-v2.yaml b/dts/bindings/mspi/nordic,nrf-qspi-v2.yaml new file mode 100644 index 000000000000..5ad8a6fd2452 --- /dev/null +++ b/dts/bindings/mspi/nordic,nrf-qspi-v2.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic QSPI v2 Interface using SSI IP + +compatible: "nordic,nrf-qspi-v2" + +include: snps,designware-ssi.yaml diff --git a/dts/bindings/mspi/snps,designware-ssi.yaml b/dts/bindings/mspi/snps,designware-ssi.yaml index fb516cb78358..7677325493b2 100644 --- a/dts/bindings/mspi/snps,designware-ssi.yaml +++ b/dts/bindings/mspi/snps,designware-ssi.yaml @@ -14,6 +14,10 @@ properties: interrupts: required: true + packet-data-limit: + required: true + const: 65536 + aux-reg-enable: type: boolean description: | @@ -43,3 +47,20 @@ properties: description: | Number of entries in the RX FIFO above which the controller gets an RX interrupt. Maximum value is the RX FIFO depth - 1. + + dma-transmit-data-level: + type: int + description: | + When in DMA mode, the transmit data level field controls the level at which a DMA request + is made by the transmit logic. A request to transmit is generated when the number of + valid data entries in the transmit FIFO is equal to or below this field value. Lower values + mean less frequent DMA triggers with larger bursts. Higher values mean fewer, smaller bursts + (lower latency, higher overhead). Range: 0-15 + + dma-receive-data-level: + type: int + description: | + When in DMA mode, the receive data level field controls the level at which a DMA request + is made by the receive logic. A request to receive is generated when the number of + valid data entries in the receive FIFO is greater than this value. Lower values mean + more frequent DMA triggers and higher values mean larger less frequent bursts. Range: 0-15 diff --git a/dts/bindings/mtd/jedec,mspi-nor.yaml b/dts/bindings/mtd/jedec,mspi-nor.yaml index 348e11cd9833..e59fe117557e 100644 --- a/dts/bindings/mtd/jedec,mspi-nor.yaml +++ b/dts/bindings/mtd/jedec,mspi-nor.yaml @@ -21,6 +21,62 @@ include: - t-exit-dpd properties: + read-frequency: + type: int + description: | + Clock frequency of device to configure in Hz for read + command, when reads are desired to be in a different + frequency than the rest of the commands. + + read-io-mode: + type: string + enum: + - "MSPI_IO_MODE_SINGLE" + - "MSPI_IO_MODE_DUAL" + - "MSPI_IO_MODE_DUAL_1_1_2" + - "MSPI_IO_MODE_DUAL_1_2_2" + - "MSPI_IO_MODE_QUAD" + - "MSPI_IO_MODE_QUAD_1_1_4" + - "MSPI_IO_MODE_QUAD_1_4_4" + - "MSPI_IO_MODE_OCTAL" + - "MSPI_IO_MODE_OCTAL_1_1_8" + - "MSPI_IO_MODE_OCTAL_1_8_8" + - "MSPI_IO_MODE_HEX" + - "MSPI_IO_MODE_HEX_8_8_16" + - "MSPI_IO_MODE_HEX_8_16_16" + description: | + MSPI I/O mode setting for read command when desired to + be different from base device `mspi-io-mode` for the rest + of the commands. + + write-frequency: + type: int + description: | + Clock frequency of device to configure in Hz for write + command, when write are desired to be in a different + frequency than the rest of the commands. + + write-io-mode: + type: string + enum: + - "MSPI_IO_MODE_SINGLE" + - "MSPI_IO_MODE_DUAL" + - "MSPI_IO_MODE_DUAL_1_1_2" + - "MSPI_IO_MODE_DUAL_1_2_2" + - "MSPI_IO_MODE_QUAD" + - "MSPI_IO_MODE_QUAD_1_1_4" + - "MSPI_IO_MODE_QUAD_1_4_4" + - "MSPI_IO_MODE_OCTAL" + - "MSPI_IO_MODE_OCTAL_1_1_8" + - "MSPI_IO_MODE_OCTAL_1_8_8" + - "MSPI_IO_MODE_HEX" + - "MSPI_IO_MODE_HEX_8_8_16" + - "MSPI_IO_MODE_HEX_8_16_16" + description: | + MSPI I/O mode setting for write command when desired to + be different from base device `mspi-io-mode` for the rest + of the commands. + reset-gpios: type: phandle-array description: | diff --git a/dts/bindings/power-domain/nordic,nrfs-swext.yaml b/dts/bindings/power-domain/nordic,nrfs-swext.yaml new file mode 100644 index 000000000000..a504f4d97cdd --- /dev/null +++ b/dts/bindings/power-domain/nordic,nrfs-swext.yaml @@ -0,0 +1,26 @@ +# Copyright 2025 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic NRFS SWEXT power domain + +compatible: "nordic,nrfs-swext" + +include: power-domain.yaml + +properties: + "#power-domain-cells": + const: 0 + + max-current-ua: + type: int + description: Maxmimum supported current in microamps. + required: true + + current-limit-ua: + type: int + description: Maxmimum allowed current in microamps. + required: true + + power-down-clamp: + type: boolean + description: Enable ground clamp on output when powered down. diff --git a/dts/bindings/power-domain/silabs,siwx91x-power-domain.yaml b/dts/bindings/power-domain/silabs,siwx91x-power-domain.yaml new file mode 100644 index 000000000000..cd0bafa8237e --- /dev/null +++ b/dts/bindings/power-domain/silabs,siwx91x-power-domain.yaml @@ -0,0 +1,5 @@ +description: Silabs siwx91x soc power domain + +compatible: "silabs,siwx91x-power-domain" + +include: power-domain.yaml diff --git a/dts/bindings/serial/nordic,nrf-uarte.yaml b/dts/bindings/serial/nordic,nrf-uarte.yaml index 4e9ccb0dd400..c8eb2bbc758d 100644 --- a/dts/bindings/serial/nordic,nrf-uarte.yaml +++ b/dts/bindings/serial/nordic,nrf-uarte.yaml @@ -24,3 +24,11 @@ properties: type: boolean description: | UARTE allows usage of cross domain pins with constant latency mode required. + + timer: + type: phandle + description: | + Timer instance used to count received bytes. Due to issues with frame timeout + feature it is required to reliably receive data in cases where flow control + is not used and new byte can appear on the line when frame timeout expires + but before it is handled. diff --git a/dts/bindings/spi/nordic,nrf-exmif-spi.yaml b/dts/bindings/spi/nordic,nrf-exmif-spi.yaml new file mode 100644 index 000000000000..d988b4146878 --- /dev/null +++ b/dts/bindings/spi/nordic,nrf-exmif-spi.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic External Memory Interface (EXMIF) used in SPI mode only + +compatible: "nordic,nrf-exmif-spi" + +include: snps,designware-spi.yaml diff --git a/dts/bindings/spi/nordic,nrf-spi-common.yaml b/dts/bindings/spi/nordic,nrf-spi-common.yaml index e76d785b2f42..dc81950aed3d 100644 --- a/dts/bindings/spi/nordic,nrf-spi-common.yaml +++ b/dts/bindings/spi/nordic,nrf-spi-common.yaml @@ -61,13 +61,3 @@ properties: and SPI master again keeps the line in the low state Please note that the line must be configured and properly handled on both sides for the mechanism to work correctly. - - default-gpio-port: - type: phandle - description: | - SPI default GPIO port. - - cross-domain-pins-supported: - type: boolean - description: | - SPI allows usage of cross domain pins with constant latency mode required. diff --git a/dts/vendor/nordic/nrf54h20.dtsi b/dts/vendor/nordic/nrf54h20.dtsi index b6bf93238b49..5c445b9d5c75 100644 --- a/dts/vendor/nordic/nrf54h20.dtsi +++ b/dts/vendor/nordic/nrf54h20.dtsi @@ -13,7 +13,6 @@ #include #include #include -#include /delete-node/ &sw_pwm; @@ -31,7 +30,7 @@ device_type = "cpu"; clocks = <&cpuapp_hsfll>; clock-frequency = ; - cpu-power-states = <&idle_cache_disabled &s2ram>; + cpu-power-states = <&idle_cache_retained &idle_cache_disabled &s2ram>; }; cpurad: cpu@3 { @@ -40,7 +39,7 @@ device_type = "cpu"; clocks = <&cpurad_hsfll>; clock-frequency = ; - cpu-power-states = <&idle_cache_disabled>; + cpu-power-states = <&idle_cache_retained &idle_cache_disabled>; }; cpuppr: cpu@d { @@ -130,7 +129,13 @@ power-states { // substate-id = <0>; is reserved for "idle", cache powered on - // substate-id = <1>; is reserved for "idle-cache-retained" + idle_cache_retained: idle_cache_retained { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <700>; + exit-latency-us = <5>; + }; idle_cache_disabled: idle_cache_disabled { compatible = "zephyr,power-state"; power-state-name = "suspend-to-idle"; @@ -247,6 +252,15 @@ }; }; + swext: swext { + compatible = "nordic,nrfs-swext"; + status = "disabled"; + max-current-ua = <7500>; + current-limit-ua = <7500>; + zephyr,pm-device-runtime-auto; + #power-domain-cells = <0>; + }; + soc { #address-cells = <1>; #size-cells = <1>; @@ -254,7 +268,6 @@ mram1x: mram@e000000 { compatible = "nordic,mram"; reg = <0xe000000 DT_SIZE_K(2048)>; - power-domains = <&gdpwr_fast_active_0>; erase-block-size = <4096>; write-block-size = <16>; }; @@ -482,6 +495,15 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "disabled"; + }; + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "disabled"; + }; }; ccm030: ccm@3a000 { @@ -526,10 +548,82 @@ interrupts = <127 NRF_DEFAULT_IRQ_PRIORITY>; }; - tddconf: tddconf@1000 { - compatible = "nordic,nrf-tddconf"; - reg = <0x1000 0x10>; + hsfll200: clock@4000 { + compatible = "fixed-clock"; + reg = <0x4000 0x1000>; + #clock-cells = <0>; status = "disabled"; + clock-frequency = ; + }; + + coresight: coresight@40000 { + compatible = "nordic,coresight-nrf"; + reg = <0x40000 0x11000>; + status = "disabled"; + nordic,clockpin-enable = ; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x40000 0x11000>; + + tsgen: tsgen@1000 { + reg = <0x1000 0x1000>; + }; + + stm: stm@2000 { + reg = <0x2000 0x1000>; + }; + + tpiu: tpiu@3000 { + reg = <0x3000 0x1000>; + }; + + etb: etb@4000 { + reg = <0x4000 0x1000>; + }; + + etr: etr@5000 { + reg = <0x5000 0x1000>; + }; + + cti210: cti@6000 { + reg = <0x6000 0x1000>; + }; + + cti211: cti@7000 { + reg = <0x7000 0x1000>; + }; + + atbreplicator210: atbreplicator@8000 { + reg = <0x8000 0x1000>; + }; + + atbreplicator211: atbreplicator@9000 { + reg = <0x9000 0x1000>; + }; + + atbreplicator212: atbreplicator@A000 { + reg = <0xA000 0x1000>; + }; + + atbreplicator213: atbreplicator@B000 { + reg = <0xB000 0x1000>; + }; + + atbfunnel210: atbfunnel@C000 { + reg = <0xC000 0x1000>; + }; + + atbfunnel211: atbfunnel@D000 { + reg = <0xD000 0x1000>; + }; + + atbfunnel212: atbfunnel@E000 { + reg = <0xE000 0x1000>; + }; + + atbfunnel213: atbfunnel@F000 { + reg = <0xF000 0x1000>; + }; }; }; @@ -545,7 +639,6 @@ reg = <0x86000 0x1000>, <0x2f700000 0x40000>; reg-names = "wrapper", "core"; interrupts = <134 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_fast_active_0>; num-in-eps = <8>; num-out-eps = <10>; ghwcfg1 = <0xaa555000>; @@ -561,8 +654,8 @@ reg = <0x95000 0x500 0x95500 0xb00>; reg-names = "wrapper", "core"; interrupts = <149 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_fast_active_0>; clock-frequency = ; + packet-data-limit = <65536>; fifo-depth = <32>; status = "disabled"; }; @@ -570,21 +663,18 @@ cpusec_bellboard: mailbox@99000 { reg = <0x99000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_fast_active_0>; #mbox-cells = <1>; }; cpuapp_bellboard: mailbox@9a000 { reg = <0x9a000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_fast_active_0>; #mbox-cells = <1>; }; cpurad_bellboard: mailbox@9b000 { reg = <0x9b000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_fast_active_0>; #mbox-cells = <1>; }; @@ -625,7 +715,6 @@ compatible = "nordic,nrf-vpr-coprocessor"; reg = <0x8d4000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_fast_active_1>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x8d4000 0x1000>; @@ -647,7 +736,6 @@ interrupts = <216 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&canpll>, <&hsfll120>; clock-names = "auxpll", "hsfll"; - power-domains = <&gdpwr_fast_active_1>; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; status = "disabled"; }; @@ -656,7 +744,6 @@ compatible = "nordic,nrf-dppic-global"; reg = <0x8e1000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_fast_active_1>; }; timer120: timer@8e2000 { @@ -665,7 +752,6 @@ status = "disabled"; cc-num = <6>; interrupts = <226 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_fast_active_1>; max-bit-width = <32>; clocks = <&hsfll120>; prescaler = <0>; @@ -677,7 +763,6 @@ status = "disabled"; cc-num = <6>; interrupts = <227 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_fast_active_1>; max-bit-width = <32>; clocks = <&hsfll120>; prescaler = <0>; @@ -689,7 +774,6 @@ status = "disabled"; interrupts = <228 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; - power-domains = <&gdpwr_fast_active_1>; #pwm-cells = <3>; idleout-supported; }; @@ -698,7 +782,6 @@ compatible = "nordic,nrf-spis"; reg = <0x8e5000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_fast_active_1>; easydma-maxcnt-bits = <15>; interrupts = <229 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; @@ -712,7 +795,6 @@ compatible = "nordic,nrf-spim"; reg = <0x8e6000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_fast_active_1>; easydma-maxcnt-bits = <15>; interrupts = <230 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; @@ -730,9 +812,9 @@ status = "disabled"; interrupts = <230 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; - power-domains = <&gdpwr_fast_active_1>; endtx-stoptx-supported; frame-timeout-supported; + zephyr,pm-device-runtime-auto; }; spi121: spi@8e7000 { @@ -742,7 +824,6 @@ easydma-maxcnt-bits = <15>; interrupts = <231 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; - power-domains = <&gdpwr_fast_active_1>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -758,7 +839,6 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x908000 0x1000>; - power-domains = <&gdpwr_slow_active>; cpuppr_vevif_tx: mailbox@0 { compatible = "nordic,nrf-vevif-task-tx"; @@ -774,7 +854,6 @@ compatible = "nordic,nrf-ipct-global"; reg = <0x921000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_slow_main>; channels = <8>; global-domain-id = <13>; }; @@ -783,7 +862,6 @@ compatible = "nordic,nrf-dppic-global"; reg = <0x922000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_slow_main>; }; rtc130: rtc@928000 { @@ -793,7 +871,6 @@ cc-num = <4>; clock-frequency = <32768>; interrupts = <296 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_slow_main>; clocks = <&lfclk>; prescaler = <1>; }; @@ -805,7 +882,6 @@ cc-num = <4>; clock-frequency = <32768>; interrupts = <297 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_slow_main>; clocks = <&lfclk>; prescaler = <1>; }; @@ -816,7 +892,6 @@ status = "disabled"; interrupts = <299 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&lfclk>; - power-domains = <&gdpwr_slow_main>; }; wdt132: watchdog@92c000 { @@ -825,7 +900,6 @@ status = "disabled"; interrupts = <300 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&lfclk>; - power-domains = <&gdpwr_slow_main>; }; egu130: egu@92d000 { @@ -833,14 +907,12 @@ reg = <0x92d000 0x1000>; status = "disabled"; interrupts = <301 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_slow_main>; }; gpiote130: gpiote@934000 { compatible = "nordic,nrf-gpiote"; reg = <0x934000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_slow_main>; instance = <130>; }; @@ -850,19 +922,10 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gdpwr_slow_main>; gpiote-instance = <&gpiote130>; ngpios = <12>; port = <0>; zephyr,pm-device-runtime-auto; - - gpio_pad_group0: pad-group { - compatible = "nordic,nrf-gpio-pad-group"; - power-domains = <&gdpwr_slow_main>; - retain-mask = <0xFFF>; - zephyr,pm-device-runtime-auto; - status = "disabled"; - }; }; gpio1: gpio@938200 { @@ -871,19 +934,10 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gdpwr_slow_main>; gpiote-instance = <&gpiote130>; ngpios = <12>; port = <1>; zephyr,pm-device-runtime-auto; - - gpio_pad_group1: pad-group { - compatible = "nordic,nrf-gpio-pad-group"; - power-domains = <&gdpwr_slow_main>; - retain-mask = <0xFFF>; - zephyr,pm-device-runtime-auto; - status = "disabled"; - }; }; gpio2: gpio@938400 { @@ -892,19 +946,10 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gdpwr_slow_main>; gpiote-instance = <&gpiote130>; ngpios = <12>; port = <2>; zephyr,pm-device-runtime-auto; - - gpio_pad_group2: pad-group { - compatible = "nordic,nrf-gpio-pad-group"; - power-domains = <&gdpwr_slow_main>; - retain-mask = <0xFFF>; - zephyr,pm-device-runtime-auto; - status = "disabled"; - }; }; gpio6: gpio@938c00 { @@ -913,18 +958,9 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gdpwr_slow_main>; ngpios = <14>; port = <6>; zephyr,pm-device-runtime-auto; - - gpio_pad_group6: pad-group { - compatible = "nordic,nrf-gpio-pad-group"; - power-domains = <&gdpwr_fast_active_1>; - retain-mask = <0x3FFF>; - zephyr,pm-device-runtime-auto; - status = "disabled"; - }; }; gpio7: gpio@938e00 { @@ -933,18 +969,9 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gdpwr_slow_main>; ngpios = <8>; port = <7>; zephyr,pm-device-runtime-auto; - - gpio_pad_group7: pad-group { - compatible = "nordic,nrf-gpio-pad-group"; - power-domains = <&gdpwr_fast_active_1>; - retain-mask = <0xFF>; - zephyr,pm-device-runtime-auto; - status = "disabled"; - }; }; gpio9: gpio@939200 { @@ -953,26 +980,16 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gdpwr_slow_main>; gpiote-instance = <&gpiote130>; ngpios = <6>; port = <9>; zephyr,pm-device-runtime-auto; - - gpio_pad_group9: pad-group { - compatible = "nordic,nrf-gpio-pad-group"; - power-domains = <&gdpwr_slow_main>; - retain-mask = <0x3F>; - zephyr,pm-device-runtime-auto; - status = "disabled"; - }; }; dppic131: dppic@981000 { compatible = "nordic,nrf-dppic-global"; reg = <0x981000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_slow_active>; }; adc: adc@982000 { @@ -981,7 +998,12 @@ interrupts = <386 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; #io-channel-cells = <1>; - power-domains = <&gdpwr_slow_active>; + /* + * This device is actually in the gdpwr_slow_active domain, but + * all of its analog inputs are routed to pads in the + * gdpwr_slow_main. Request gdpwr_slow_main and rely on the + * device HW to force its own power domain on while ENABLED. + */ zephyr,pm-device-runtime-auto; }; @@ -994,7 +1016,12 @@ reg = <0x983000 0x1000>; status = "disabled"; interrupts = <387 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_slow_active>; + /* + * This device is actually in the gdpwr_slow_active domain, but + * all of its analog inputs are routed to pads in the + * gdpwr_slow_main. Request gdpwr_slow_main and rely on the + * device HW to force its own power domain on while ENABLED. + */ }; temp: temperature-sensor@984000 { @@ -1002,7 +1029,6 @@ reg = <0x984000 0x1000>; interrupts = <388 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; - power-domains = <&gdpwr_slow_active>; }; nfct: nfct@985000 { @@ -1010,14 +1036,12 @@ reg = <0x985000 0x1000>; status = "disabled"; interrupts = <389 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_slow_active>; }; dppic132: dppic@991000 { compatible = "nordic,nrf-dppic-global"; reg = <0x991000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_slow_active>; }; pdm0: pdm@993000 { @@ -1026,7 +1050,6 @@ status = "disabled"; interrupts = <403 NRF_DEFAULT_IRQ_PRIORITY>; nordic,clockpin-enable = ; - power-domains = <&gdpwr_slow_active>; }; qdec130: qdec@994000 { @@ -1034,7 +1057,6 @@ reg = <0x994000 0x1000>; status = "disabled"; interrupts = <404 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_slow_active>; }; qdec131: qdec@995000 { @@ -1042,7 +1064,6 @@ reg = <0x995000 0x1000>; status = "disabled"; interrupts = <405 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gdpwr_slow_active>; }; grtc: grtc@99c000 { @@ -1052,14 +1073,12 @@ cc-num = <16>; clocks = <&lfclk>, <&fll16m>; clock-names = "lfclock", "hfclock"; - power-domains = <&gdpwr_slow_active>; }; dppic133: dppic@9a1000 { compatible = "nordic,nrf-dppic-global"; reg = <0x9a1000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_slow_active>; }; timer130: timer@9a2000 { @@ -1069,7 +1088,6 @@ cc-num = <6>; interrupts = <418 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1081,7 +1099,6 @@ cc-num = <6>; interrupts = <419 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1092,7 +1109,6 @@ status = "disabled"; interrupts = <420 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; #pwm-cells = <3>; idleout-supported; }; @@ -1103,7 +1119,6 @@ status = "disabled"; interrupts = <421 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1119,7 +1134,6 @@ easydma-maxcnt-bits = <15>; interrupts = <421 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1137,10 +1151,10 @@ status = "disabled"; interrupts = <421 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; + zephyr,pm-device-runtime-auto; }; i2c131: i2c@9a6000 { @@ -1149,7 +1163,6 @@ status = "disabled"; interrupts = <422 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1165,7 +1178,6 @@ easydma-maxcnt-bits = <15>; interrupts = <422 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1183,7 +1195,6 @@ status = "disabled"; interrupts = <422 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; @@ -1194,7 +1205,6 @@ compatible = "nordic,nrf-dppic-global"; reg = <0x9b1000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_slow_active>; }; timer132: timer@9b2000 { @@ -1204,7 +1214,6 @@ cc-num = <6>; interrupts = <434 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1216,7 +1225,6 @@ cc-num = <6>; interrupts = <435 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1227,7 +1235,6 @@ status = "disabled"; interrupts = <436 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; #pwm-cells = <3>; idleout-supported; }; @@ -1238,7 +1245,6 @@ status = "disabled"; interrupts = <437 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1254,7 +1260,6 @@ easydma-maxcnt-bits = <15>; interrupts = <437 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1272,10 +1277,10 @@ status = "disabled"; interrupts = <437 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; + zephyr,pm-device-runtime-auto; }; i2c133: i2c@9b6000 { @@ -1284,7 +1289,6 @@ status = "disabled"; interrupts = <438 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1300,7 +1304,6 @@ easydma-maxcnt-bits = <15>; interrupts = <438 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1318,17 +1321,16 @@ status = "disabled"; interrupts = <438 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; + zephyr,pm-device-runtime-auto; }; dppic135: dppic@9c1000 { compatible = "nordic,nrf-dppic-global"; reg = <0x9c1000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_slow_active>; }; timer134: timer@9c2000 { @@ -1338,7 +1340,6 @@ cc-num = <6>; interrupts = <450 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1350,7 +1351,6 @@ cc-num = <6>; interrupts = <451 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1362,7 +1362,6 @@ interrupts = <452 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; #pwm-cells = <3>; - power-domains = <&gdpwr_slow_active>; idleout-supported; }; @@ -1372,7 +1371,6 @@ status = "disabled"; interrupts = <453 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1388,7 +1386,6 @@ easydma-maxcnt-bits = <15>; interrupts = <453 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1406,10 +1403,10 @@ status = "disabled"; interrupts = <453 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; + zephyr,pm-device-runtime-auto; }; i2c135: i2c@9c6000 { @@ -1418,7 +1415,6 @@ status = "disabled"; interrupts = <454 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1434,7 +1430,6 @@ easydma-maxcnt-bits = <15>; interrupts = <454 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1452,17 +1447,16 @@ status = "disabled"; interrupts = <454 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; + zephyr,pm-device-runtime-auto; }; dppic136: dppic@9d1000 { compatible = "nordic,nrf-dppic-global"; reg = <0x9d1000 0x1000>; status = "disabled"; - power-domains = <&gdpwr_slow_active>; }; timer136: timer@9d2000 { @@ -1472,7 +1466,6 @@ cc-num = <6>; interrupts = <466 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1484,7 +1477,6 @@ cc-num = <6>; interrupts = <467 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1496,7 +1488,6 @@ interrupts = <468 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; #pwm-cells = <3>; - power-domains = <&gdpwr_slow_active>; idleout-supported; }; @@ -1506,7 +1497,6 @@ status = "disabled"; interrupts = <469 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1522,7 +1512,6 @@ easydma-maxcnt-bits = <15>; interrupts = <469 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1540,7 +1529,6 @@ status = "disabled"; interrupts = <469 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; @@ -1553,7 +1541,6 @@ status = "disabled"; interrupts = <470 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1569,7 +1556,6 @@ easydma-maxcnt-bits = <15>; interrupts = <470 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1587,10 +1573,10 @@ status = "disabled"; interrupts = <470 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; + zephyr,pm-device-runtime-auto; }; tdm130: tdm@992000 { @@ -1602,7 +1588,6 @@ interrupts = <402 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = , ; }; @@ -1616,7 +1601,6 @@ interrupts = <407 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; clocks = <&fll16m>; - power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = , ; }; diff --git a/dts/vendor/nordic/nrf54l20.dtsi b/dts/vendor/nordic/nrf54l20.dtsi new file mode 100644 index 000000000000..bee70effa0e8 --- /dev/null +++ b/dts/vendor/nordic/nrf54l20.dtsi @@ -0,0 +1,852 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/delete-node/ &sw_pwm; + +/* Domain IDs. Can be used to specify channel links in IPCT nodes. */ +#define NRF_DOMAIN_ID_APPLICATION 0 +#define NRF_DOMAIN_ID_FLPR 1 + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpuapp: cpu@0 { + compatible = "arm,cortex-m33f"; + reg = <0>; + device_type = "cpu"; + clocks = <&hfpll>; + #address-cells = <1>; + #size-cells = <1>; + + itm: itm@e0000000 { + compatible = "arm,armv8m-itm"; + reg = <0xe0000000 0x1000>; + swo-ref-frequency = ; + }; + }; + + cpuflpr: cpu@1 { + compatible = "nordic,vpr"; + reg = <1>; + device_type = "cpu"; + riscv,isa = "rv32emc"; + nordic,bus-width = <64>; + }; + }; + + clocks { + pclk: pclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + + pclk32m: pclk32m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + + lfxo: lfxo { + compatible = "nordic,nrf54l-lfxo"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + hfxo: hfxo { + compatible = "nordic,nrf54l-hfxo"; + #clock-cells = <0>; + clock-frequency = ; + startup-time-us = <1650>; + }; + + hfpll: hfpll { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + + aclk: aclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + + ficr: ficr@ffc000 { + compatible = "nordic,nrf-ficr"; + reg = <0xffc000 0x1000>; + #nordic,ficr-cells = <1>; + }; + + uicr: uicr@ffd000 { + compatible = "nordic,nrf-uicr"; + reg = <0xffd000 0x1000>; + }; + + cpuapp_sram: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(447)>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x20000000 0x6fc00>; + }; + + cpuflpr_sram: memory@2006fc00 { + compatible = "mmio-sram"; + reg = <0x2006fc00 DT_SIZE_K(64)>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x2006fc00 0x10000>; + }; + + global_peripherals: peripheral@50000000 { + ranges = <0x0 0x50000000 0x10000000>; + #address-cells = <1>; + #size-cells = <1>; + + dppic00: dppic@42000 { + compatible = "nordic,nrf-dppic"; + reg = <0x42000 0x808>; + status = "disabled"; + }; + + ppib00: ppib@44000 { + compatible = "nordic,nrf-ppib"; + reg = <0x44000 0x1000>; + status = "disabled"; + }; + + ppib01: ppib@45000 { + compatible = "nordic,nrf-ppib"; + reg = <0x45000 0x1000>; + status = "disabled"; + }; + + cpuflpr_vpr: vpr@4c000 { + compatible = "nordic,nrf-vpr-coprocessor"; + reg = <0x4c000 0x1000>; + ranges = <0x0 0x4c000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + enable-secure; + + cpuflpr_clic: interrupt-controller@f0000000 { + compatible = "nordic,nrf-clic"; + reg = <0xf0000000 0x143c>; + interrupt-controller; + #interrupt-cells = <2>; + #address-cells = <1>; + status = "disabled"; + }; + }; + + spi00: spi@4d000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x4d000 0x1000>; + interrupts = <77 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart00: uart@4d000 { + compatible = "nordic,nrf-uarte"; + reg = <0x4d000 0x1000>; + interrupts = <77 NRF_DEFAULT_IRQ_PRIORITY>; + clocks = <&hfpll>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + gpio2: gpio@50400 { + compatible = "nordic,nrf-gpio"; + gpio-controller; + reg = <0x50400 0x300>; + #gpio-cells = <2>; + ngpios = <11>; + status = "disabled"; + port = <2>; + }; + + timer00: timer@55000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0x55000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <85 NRF_DEFAULT_IRQ_PRIORITY>; + clocks = <&hfpll>; + prescaler = <0>; + }; + + dppic10: dppic@82000 { + compatible = "nordic,nrf-dppic"; + reg = <0x82000 0x808>; + status = "disabled"; + }; + + ppib10: ppib@83000 { + compatible = "nordic,nrf-ppib"; + reg = <0x83000 0x1000>; + status = "disabled"; + }; + + ppib11: ppib@84000 { + compatible = "nordic,nrf-ppib"; + reg = <0x84000 0x1000>; + status = "disabled"; + }; + + timer10: timer@85000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0x85000 0x1000>; + cc-num = <8>; + max-bit-width = <32>; + interrupts = <133 NRF_DEFAULT_IRQ_PRIORITY>; + clocks = <&hfxo>; + prescaler = <0>; + }; + + egu10: egu@87000 { + compatible = "nordic,nrf-egu"; + reg = <0x87000 0x1000>; + interrupts = <135 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + radio: radio@8a000 { + compatible = "nordic,nrf-radio"; + reg = <0x8a000 0x1000>; + interrupts = <138 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + dfe-supported; + ieee802154-supported; + ble-2mbps-supported; + ble-coded-phy-supported; + cs-supported; + + ieee802154: ieee802154 { + compatible = "nordic,nrf-ieee802154"; + status = "disabled"; + }; + + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "disabled"; + }; + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "disabled"; + }; + }; + + dppic20: dppic@c2000 { + compatible = "nordic,nrf-dppic"; + reg = <0xc2000 0x808>; + status = "disabled"; + }; + + ppib20: ppib@c3000 { + compatible = "nordic,nrf-ppib"; + reg = <0xc3000 0x1000>; + status = "disabled"; + }; + + ppib21: ppib@c4000 { + compatible = "nordic,nrf-ppib"; + reg = <0xc4000 0x1000>; + status = "disabled"; + }; + + ppib22: ppib@c5000 { + compatible = "nordic,nrf-ppib"; + reg = <0xc5000 0x1000>; + status = "disabled"; + }; + + i2c20: i2c@c6000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc6000 0x1000>; + interrupts = <198 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi20: spi@c6000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc6000 0x1000>; + interrupts = <198 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart20: uart@c6000 { + compatible = "nordic,nrf-uarte"; + reg = <0xc6000 0x1000>; + interrupts = <198 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + i2c21: i2c@c7000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc7000 0x1000>; + interrupts = <199 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi21: spi@c7000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc7000 0x1000>; + interrupts = <199 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart21: uart@c7000 { + compatible = "nordic,nrf-uarte"; + reg = <0xc7000 0x1000>; + interrupts = <199 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + i2c22: i2c@c8000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc8000 0x1000>; + interrupts = <200 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi22: spi@c8000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc8000 0x1000>; + interrupts = <200 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart22: uart@c8000 { + compatible = "nordic,nrf-uarte"; + reg = <0xc8000 0x1000>; + interrupts = <200 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + egu20: egu@c9000 { + compatible = "nordic,nrf-egu"; + reg = <0xc9000 0x1000>; + interrupts = <201 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + timer20: timer@ca000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xca000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <202 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + timer21: timer@cb000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xcb000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <203 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + timer22: timer@cc000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xcc000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <204 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + timer23: timer@cd000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xcd000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <205 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + timer24: timer@ce000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xce000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <206 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + pdm20: pdm@d0000 { + compatible = "nordic,nrf-pdm"; + status = "disabled"; + reg = <0xd0000 0x1000>; + interrupts = <208 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + pdm21: pdm@d1000 { + compatible = "nordic,nrf-pdm"; + status = "disabled"; + reg = <0xd1000 0x1000>; + interrupts = <209 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + pwm20: pwm@d2000 { + compatible = "nordic,nrf-pwm"; + status = "disabled"; + reg = <0xd2000 0x1000>; + interrupts = <210 NRF_DEFAULT_IRQ_PRIORITY>; + #pwm-cells = <3>; + idleout-supported; + }; + + pwm21: pwm@d3000 { + compatible = "nordic,nrf-pwm"; + status = "disabled"; + reg = <0xd3000 0x1000>; + interrupts = <211 NRF_DEFAULT_IRQ_PRIORITY>; + #pwm-cells = <3>; + idleout-supported; + }; + + pwm22: pwm@d4000 { + compatible = "nordic,nrf-pwm"; + status = "disabled"; + reg = <0xd4000 0x1000>; + interrupts = <212 NRF_DEFAULT_IRQ_PRIORITY>; + #pwm-cells = <3>; + idleout-supported; + }; + + adc: adc@d5000 { + compatible = "nordic,nrf-saadc"; + reg = <0xd5000 0x1000>; + interrupts = <213 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + #io-channel-cells = <1>; + zephyr,pm-device-runtime-auto; + }; + + nfct: nfct@d6000 { + compatible = "nordic,nrf-nfct"; + reg = <0xd6000 0x1000>; + interrupts = <214 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + temp: temp@d7000 { + compatible = "nordic,nrf-temp"; + reg = <0xd7000 0x1000>; + interrupts = <215 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + gpio1: gpio@d8200 { + compatible = "nordic,nrf-gpio"; + gpio-controller; + reg = <0xd8200 0x300>; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + port = <1>; + gpiote-instance = <&gpiote20>; + }; + + gpiote20: gpiote@da000 { + compatible = "nordic,nrf-gpiote"; + reg = <0xda000 0x1000>; + status = "disabled"; + instance = <20>; + }; + + qdec20: qdec@e0000 { + compatible = "nordic,nrf-qdec"; + reg = <0xe0000 0x1000>; + interrupts = <224 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + qdec21: qdec@e1000 { + compatible = "nordic,nrf-qdec"; + reg = <0xe1000 0x1000>; + interrupts = <225 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + grtc: grtc@e2000 { + compatible = "nordic,nrf-grtc"; + reg = <0xe2000 0x1000>; + cc-num = <12>; + clocks = <&lfxo>, <&pclk>; + clock-names = "lfclock", "hfclock"; + status = "disabled"; + }; + + tdm: tdm@e8000 { + compatible = "nordic,nrf-tdm"; + easydma-maxcnt-bits = <15>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xe8000 0x1000>; + interrupts = <232 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + clocks = <&pclk32m>; + }; + + i2c23: i2c@ed000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xed000 0x1000>; + interrupts = <237 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi23: spi@ed000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xed000 0x1000>; + interrupts = <237 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart23: uart@ed000 { + compatible = "nordic,nrf-uarte"; + reg = <0xed000 0x1000>; + interrupts = <237 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + i2c24: i2c@ee000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xee000 0x1000>; + interrupts = <238 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi24: spi@ee000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xee000 0x1000>; + interrupts = <238 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart24: uart@ee000 { + compatible = "nordic,nrf-uarte"; + reg = <0xee000 0x1000>; + interrupts = <238 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + dppic30: dppic@102000 { + compatible = "nordic,nrf-dppic"; + reg = <0x102000 0x808>; + status = "disabled"; + }; + + ppib30: ppib@103000 { + compatible = "nordic,nrf-ppib"; + reg = <0x103000 0x1000>; + status = "disabled"; + }; + + i2c30: i2c@104000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x104000 0x1000>; + interrupts = <260 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi30: spi@104000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x104000 0x1000>; + interrupts = <260 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart30: uart@104000 { + compatible = "nordic,nrf-uarte"; + reg = <0x104000 0x1000>; + interrupts = <260 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + comp: comparator@106000 { + /* + * Use compatible "nordic,nrf-comp" to configure as COMP + * Use compatible "nordic,nrf-lpcomp" to configure as LPCOMP + */ + compatible = "nordic,nrf-comp"; + reg = <0x106000 0x1000>; + status = "disabled"; + interrupts = <262 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + wdt30: watchdog@108000 { + compatible = "nordic,nrf-wdt"; + reg = <0x108000 0x620>; + interrupts = <264 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + wdt31: watchdog@109000 { + compatible = "nordic,nrf-wdt"; + reg = <0x109000 0x620>; + interrupts = <265 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + gpio0: gpio@10a000 { + compatible = "nordic,nrf-gpio"; + gpio-controller; + reg = <0x10a000 0x300>; + #gpio-cells = <2>; + ngpios = <5>; + status = "disabled"; + port = <0>; + gpiote-instance = <&gpiote30>; + }; + + gpiote30: gpiote@10c000 { + compatible = "nordic,nrf-gpiote"; + reg = <0x10c000 0x1000>; + status = "disabled"; + instance = <30>; + }; + + clock: clock@10e000 { + compatible = "nordic,nrf-clock"; + reg = <0x10e000 0x1000>; + interrupts = <270 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + power: power@10e000 { + compatible = "nordic,nrf-power"; + reg = <0x10e000 0x1000>; + ranges = <0x0 0x10e000 0x1000>; + interrupts = <270 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + + gpregret1: gpregret1@51c { + #address-cells = <1>; + #size-cells = <1>; + compatible = "nordic,nrf-gpregret"; + reg = <0x51c 0x1>; + status = "disabled"; + }; + + gpregret2: gpregret2@520 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "nordic,nrf-gpregret"; + reg = <0x520 0x1>; + status = "disabled"; + }; + }; + + regulators: regulator@120000 { + compatible = "nordic,nrf54l-regulators"; + reg = <0x120000 0x1000>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + + vregmain: regulator@120600 { + compatible = "nordic,nrf5x-regulator"; + reg = <0x120600 0x1>; + status = "disabled"; + regulator-name = "VREGMAIN"; + regulator-initial-mode = ; + }; + }; + }; + + rram_controller: rram-controller@5004e000 { + compatible = "nordic,rram-controller"; + reg = <0x5004e000 0x1000>; + interrupts = <78 NRF_DEFAULT_IRQ_PRIORITY>; + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_rram: rram@0 { + compatible = "soc-nv-flash"; + reg = <0x0 DT_SIZE_K(1972)>; + erase-block-size = <4096>; + write-block-size = <16>; + }; + + cpuflpr_rram: rram@1ed000 { + compatible = "soc-nv-flash"; + reg = <0x1ed000 DT_SIZE_K(64)>; + erase-block-size = <4096>; + write-block-size = <16>; + }; + }; + + cpuapp_ppb: cpuapp-ppb-bus { + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_nvic: interrupt-controller@e000e100 { + #address-cells = <1>; + compatible = "arm,v8m-nvic"; + reg = <0xe000e100 0xc00>; + arm,num-irq-priority-bits = <3>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + cpuapp_systick: timer@e000e010 { + compatible = "arm,armv8m-systick"; + reg = <0xe000e010 0x10>; + status = "disabled"; + }; + }; + }; +}; diff --git a/dts/vendor/nordic/nrf54l_05_10_15.dtsi b/dts/vendor/nordic/nrf54l_05_10_15.dtsi index aa259713d2fd..5a4854440b64 100644 --- a/dts/vendor/nordic/nrf54l_05_10_15.dtsi +++ b/dts/vendor/nordic/nrf54l_05_10_15.dtsi @@ -101,11 +101,13 @@ #ifdef USE_NON_SECURE_ADDRESS_MAP global_peripherals: peripheral@40000000 { + reg = <0x40000000 0x10000000>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x40000000 0x10000000>; #else global_peripherals: peripheral@50000000 { + reg = <0x50000000 0x10000000>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x50000000 0x10000000>; @@ -250,9 +252,11 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "disabled"; + }; + bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "disabled"; @@ -311,8 +315,6 @@ rx-delay-supported; rx-delay = <1>; status = "disabled"; - default-gpio-port = <&gpio1>; - cross-domain-pins-supported; }; uart20: uart@c6000 { @@ -322,8 +324,6 @@ status = "disabled"; endtx-stoptx-supported; frame-timeout-supported; - default-gpio-port = <&gpio1>; - cross-domain-pins-supported; }; i2c21: i2c@c7000 { @@ -354,8 +354,6 @@ rx-delay-supported; rx-delay = <1>; status = "disabled"; - default-gpio-port = <&gpio1>; - cross-domain-pins-supported; }; uart21: uart@c7000 { @@ -365,8 +363,6 @@ status = "disabled"; endtx-stoptx-supported; frame-timeout-supported; - default-gpio-port = <&gpio1>; - cross-domain-pins-supported; }; i2c22: i2c@c8000 { diff --git a/dts/vendor/nordic/nrf54lm20a.dtsi b/dts/vendor/nordic/nrf54lm20a.dtsi index 0601771d496a..b4ddafac801b 100644 --- a/dts/vendor/nordic/nrf54lm20a.dtsi +++ b/dts/vendor/nordic/nrf54lm20a.dtsi @@ -96,10 +96,14 @@ #nordic,ficr-cells = <1>; }; +#ifdef USE_NON_SECURE_ADDRESS_MAP + /* intentionally empty because UICR is hardware fixed to Secure */ +#else uicr: uicr@ffd000 { compatible = "nordic,nrf-uicr"; reg = <0xffd000 0x1000>; }; +#endif cpuapp_sram: memory@20000000 { compatible = "mmio-sram"; @@ -117,10 +121,19 @@ ranges = <0x0 0x20067c00 DT_SIZE_K(96)>; }; +#ifdef USE_NON_SECURE_ADDRESS_MAP + global_peripherals: peripheral@40000000 { + reg = <0x40000000 0x10000000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x40000000 0x10000000>; +#else global_peripherals: peripheral@50000000 { + reg = <0x50000000 0x10000000>; ranges = <0x0 0x50000000 0x10000000>; #address-cells = <1>; #size-cells = <1>; +#endif dppic00: dppic@42000 { compatible = "nordic,nrf-dppic"; @@ -277,6 +290,11 @@ /* Note: In the nRF Connect SDK the SoftDevice Controller * is added and set as the default Bluetooth Controller. */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "disabled"; + }; + bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "disabled"; @@ -747,12 +765,16 @@ interrupts = <262 NRF_DEFAULT_IRQ_PRIORITY>; }; +#ifdef USE_NON_SECURE_ADDRESS_MAP + /* intentionally empty because WDT30 is hardware fixed to Secure */ +#else wdt30: watchdog@108000 { compatible = "nordic,nrf-wdt"; reg = <0x108000 0x620>; interrupts = <264 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; }; +#endif wdt31: watchdog@109000 { compatible = "nordic,nrf-wdt"; @@ -851,6 +873,15 @@ }; }; + nrf_mpc: memory@50041000 { + compatible = "nordic,nrf-mpc"; + reg = <0x50041000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + override-num = <5>; + override-granularity = <4096>; + }; + cpuapp_ppb: cpuapp-ppb-bus { #address-cells = <1>; #size-cells = <1>; diff --git a/dts/vendor/nordic/nrf54lm20a_ns_partition.dtsi b/dts/vendor/nordic/nrf54lm20a_ns_partition.dtsi new file mode 100644 index 000000000000..954dd8290453 --- /dev/null +++ b/dts/vendor/nordic/nrf54lm20a_ns_partition.dtsi @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&cpuapp_rram { + /* + * Default NVM layout on NRF54LM20A Application MCU without BL2: + * This layout matches (by necessity) that in the TF-M repository: + * + * 0x0000_0000 Secure image primary (512 KB) + * 0x0008_0000 Protected Storage Area (16 KB) + * 0x0008_4000 Internal Trusted Storage Area (16 KB) + * 0x0008_8000 OTP / NV counters area (8 KB) + * 0x0008_A000 Non-secure image primary (1356 KB) + * 0x001D_DD00 Non-secure storage, used when built with NRF_NS_STORAGE=ON, + * otherwise unused (32 KB) + */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* nRF54LM20A has 2036 kB of non-volatile memory (RRAM) but the last + * 96 kB are reserved for the FLPR MCU. + * + * This static layout needs to be the same with the upstream TF-M layout in the + * header flash_layout.h of the relevant platform. Any updates in the layout + * needs to happen both in the flash_layout.h and in this file at the same time. + */ + slot0_partition: partition@0 { + label = "image-0"; + reg = <0x0000000 DT_SIZE_K(512)>; + }; + + tfm_ps_partition: partition@80000 { + label = "tfm-ps"; + reg = <0x00080000 DT_SIZE_K(16)>; + }; + + tfm_its_partition: partition@84000 { + label = "tfm-its"; + reg = <0x00084000 DT_SIZE_K(16)>; + }; + + tfm_otp_partition: partition@88000 { + label = "tfm-otp"; + reg = <0x00088000 DT_SIZE_K(8)>; + }; + + slot0_ns_partition: partition@8A000 { + label = "image-0-nonsecure"; + reg = <0x0008A000 DT_SIZE_K(1356)>; + }; + + storage_partition: partition@1DD000 { + label = "storage"; + reg = <0x001DD000 DT_SIZE_K(32)>; + }; + }; +}; diff --git a/dts/vendor/nordic/nrf54lm20a_partition.dtsi b/dts/vendor/nordic/nrf54lm20a_partition.dtsi new file mode 100644 index 000000000000..049f87139d91 --- /dev/null +++ b/dts/vendor/nordic/nrf54lm20a_partition.dtsi @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* nRF54LM20A has 2036 kB of non-volatile memory (RRAM) but the last + * 96 kB are reserved for the FLPR MCU, so we have ~1940 kB available. + */ + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(64)>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x10000 DT_SIZE_K(922)>; + }; + + slot1_partition: partition@f6800 { + label = "image-1"; + reg = <0xf6800 DT_SIZE_K(922)>; + }; + + storage_partition: partition@1dd000 { + label = "storage"; + reg = <0x1dd000 DT_SIZE_K(32)>; + }; + }; +}; diff --git a/dts/vendor/nordic/nrf9280.dtsi b/dts/vendor/nordic/nrf9280.dtsi index fb27488e9dc4..7d887b9a2092 100644 --- a/dts/vendor/nordic/nrf9280.dtsi +++ b/dts/vendor/nordic/nrf9280.dtsi @@ -116,16 +116,17 @@ write-block-size = <16>; }; - cpuapp_uicr: uicr@fff8000 { - compatible = "nordic,nrf-uicr-v2"; - reg = <0xfff8000 DT_SIZE_K(2)>; - domain = <2>; - }; + uicr: uicr@fff8000 { + compatible = "nordic,nrf-uicr"; + reg = <0xfff8000 DT_SIZE_K(3)>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xfff8000 DT_SIZE_K(3)>; - cpurad_uicr: uicr@fffa000 { - compatible = "nordic,nrf-uicr-v2"; - reg = <0xfffa000 DT_SIZE_K(2)>; - domain = <3>; + bicr: bicr@800 { + compatible = "nordic,nrf-bicr"; + reg = <0x800 204>; + }; }; ficr: ficr@fffe000 { @@ -358,6 +359,28 @@ }; }; + tdd_peripherals: peripheral@bf000000 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0xbf000000 0x1000000>; + ranges = <0x0 0xbf000000 0x1000000>; + + tbm: tbm@3000 { + compatible = "nordic,nrf-tbm"; + reg = <0x3000 0x408>; + status = "disabled"; + interrupts = <127 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + hsfll200: clock@4000 { + compatible = "fixed-clock"; + reg = <0x4000 0x1000>; + #clock-cells = <0>; + status = "disabled"; + clock-frequency = ; + }; + }; + global_peripherals: peripheral@5f000000 { #address-cells = <1>; #size-cells = <1>; @@ -384,6 +407,7 @@ reg-names = "wrapper", "core"; interrupts = <149 NRF_DEFAULT_IRQ_PRIORITY>; clock-frequency = ; + packet-data-limit = <65536>; fifo-depth = <32>; status = "disabled"; }; diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld index 688165d0698b..c8579f2a8023 100644 --- a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -34,6 +34,39 @@ #define ROMSTART_REGION ROMABLE_REGION #endif +#if USE_PARTITION_MANAGER + +#include + +#if CONFIG_NCS_IS_VARIANT_IMAGE && defined(PM_S0_ID) +/* We are linking against S1, create symbol containing the flash ID of S0. + * This is used when writing code operating on the "other" slot. + */ +_image_1_primary_slot_id = PM_S0_ID; + +#else /* ! CONFIG_NCS_IS_VARIANT_IMAGE */ + +#ifdef PM_S1_ID +/* We are linking against S0, create symbol containing the flash ID of S1. + * This is used when writing code operating on the "other" slot. + */ +_image_1_primary_slot_id = PM_S1_ID; +#endif /* PM_S1_ID */ + +#endif /* CONFIG_NCS_IS_VARIANT_IMAGE */ + +#define ROM_ADDR PM_ADDRESS +#define ROM_SIZE PM_SIZE + +#if defined(CONFIG_PM_USE_CONFIG_SRAM_SIZE) +#define RAM_SIZE CONFIG_PM_SRAM_SIZE +#else +#define RAM_SIZE PM_SRAM_SIZE +#endif +#define RAM_ADDR PM_SRAM_ADDRESS + +#else /* ! USE_PARTITION_MANAGER */ + #if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) #define ROM_ADDR RAM_ADDR #else @@ -55,6 +88,23 @@ #define RAM_SIZE (CONFIG_SRAM_SIZE * 1K) #define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS +#endif /* USE_PARTITION_MANAGER */ + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay) +#define CCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ccm)) +#define CCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ccm)) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) +#define ITCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_itcm)) +#define ITCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_itcm)) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +#define DTCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_dtcm)) +#define DTCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_dtcm)) +#endif + #if defined(CONFIG_CUSTOM_SECTION_ALIGN) _region_min_align = CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE; #else diff --git a/include/zephyr/arch/common/pm_s2ram.h b/include/zephyr/arch/common/pm_s2ram.h index 34c544c769b9..322cefe6ebb2 100644 --- a/include/zephyr/arch/common/pm_s2ram.h +++ b/include/zephyr/arch/common/pm_s2ram.h @@ -63,8 +63,8 @@ int arch_pm_s2ram_suspend(pm_s2ram_system_off_fn_t system_off); * Function is called when system state is stored to RAM, just before going to system * off. * - * Default implementation is setting a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING - * allows custom implementation. + * Default implementation is setting a magic word in RAM used if + * CONFIG_HAS_PM_S2RAM_CUSTOM_MARKING is not set. */ void pm_s2ram_mark_set(void); @@ -74,8 +74,8 @@ void pm_s2ram_mark_set(void); * Function is used to determine if resuming after suspend-to-RAM shall be performed * or standard boot code shall be executed. * - * Default implementation is checking a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING - * allows custom implementation. + * Default implementation is checking a magic word in RAM used if + * CONFIG_HAS_PM_S2RAM_CUSTOM_MARKING is not set. * * @retval true if marking is found which indicates resuming after suspend-to-RAM. * @retval false if marking is not found which indicates standard boot. diff --git a/include/zephyr/arch/riscv/irq.h b/include/zephyr/arch/riscv/irq.h index 8408912716a7..c3c4baff3518 100644 --- a/include/zephyr/arch/riscv/irq.h +++ b/include/zephyr/arch/riscv/irq.h @@ -83,6 +83,15 @@ extern void z_riscv_irq_vector_set(unsigned int irq); z_riscv_irq_vector_set(irq_p); \ } +#ifdef CONFIG_PM +extern void arch_isr_direct_pm(void); +#define ARCH_ISR_DIRECT_PM() arch_isr_direct_pm() +#else +#define ARCH_ISR_DIRECT_PM() \ + do { \ + } while (false) +#endif + #define ARCH_ISR_DIRECT_HEADER() arch_isr_direct_header() #define ARCH_ISR_DIRECT_FOOTER(swap) arch_isr_direct_footer(swap) diff --git a/include/zephyr/bluetooth/assigned_numbers.h b/include/zephyr/bluetooth/assigned_numbers.h new file mode 100644 index 000000000000..44c69d16a227 --- /dev/null +++ b/include/zephyr/bluetooth/assigned_numbers.h @@ -0,0 +1,1473 @@ +/** @file + * @brief Bluetooth Assigned Numbers, codes and identifiers. + */ + +/* + * Copyright (c) 2015-2025 Intel Corporation + * Copyright (c) 2017-2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_ASSIGNED_NUMBERS_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_ASSIGNED_NUMBERS_H_ + +/** + * @brief Bluetooth Assigned Numbers, codes and identifiers. + * @defgroup bt_assigned_numbers Assigned Numbers. + * @since 1.0 + * @version 1.0.0 + * @ingroup bluetooth + * @{ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Core Specification Assigned Numbers + * @defgroup bt_assigned_numbers_core Core Specification Assigned Numbers + * @ingroup bt_assigned_numbers + * @{ + */ + +/** + * @name Appearance Numbers + * + * Last Modified on 2023-01-05 + * @{ + */ + +/** Generic Unknown */ +#define BT_APPEARANCE_UNKNOWN 0x0000 +/** Generic Phone */ +#define BT_APPEARANCE_GENERIC_PHONE 0x0040 +/** Generic Computer */ +#define BT_APPEARANCE_GENERIC_COMPUTER 0x0080 +/** Desktop Workstation */ +#define BT_APPEARANCE_COMPUTER_DESKTOP_WORKSTATION 0x0081 +/** Server-class Computer */ +#define BT_APPEARANCE_COMPUTER_SERVER_CLASS 0x0082 +/** Laptop */ +#define BT_APPEARANCE_COMPUTER_LAPTOP 0x0083 +/** Handheld PC/PDA (clamshell) */ +#define BT_APPEARANCE_COMPUTER_HANDHELD_PCPDA 0x0084 +/** Palm­size PC/PDA */ +#define BT_APPEARANCE_COMPUTER_PALMSIZE_PCPDA 0x0085 +/** Wearable computer (watch size) */ +#define BT_APPEARANCE_COMPUTER_WEARABLE_COMPUTER 0x0086 +/** Tablet */ +#define BT_APPEARANCE_COMPUTER_TABLET 0x0087 +/** Docking Station */ +#define BT_APPEARANCE_COMPUTER_DOCKING_STATION 0x0088 +/** All in One */ +#define BT_APPEARANCE_COMPUTER_ALL_IN_ONE 0x0089 +/** Blade Server */ +#define BT_APPEARANCE_COMPUTER_BLADE_SERVER 0x008A +/** Convertible */ +#define BT_APPEARANCE_COMPUTER_CONVERTIBLE 0x008B +/** Detachable */ +#define BT_APPEARANCE_COMPUTER_DETACHABLE 0x008C +/** IoT Gateway */ +#define BT_APPEARANCE_COMPUTER_IOT_GATEWAY 0x008D +/** Mini PC */ +#define BT_APPEARANCE_COMPUTER_MINI_PC 0x008E +/** Stick PC */ +#define BT_APPEARANCE_COMPUTER_STICK_PC 0x008F +/** Generic Watch */ +#define BT_APPEARANCE_GENERIC_WATCH 0x00C0 +/** Sports Watch */ +#define BT_APPEARANCE_SPORTS_WATCH 0x00C1 +/** Smartwatch */ +#define BT_APPEARANCE_SMARTWATCH 0x00C2 +/** Generic Clock */ +#define BT_APPEARANCE_GENERIC_CLOCK 0x0100 +/** Generic Display */ +#define BT_APPEARANCE_GENERIC_DISPLAY 0x0140 +/** Generic Remote Control */ +#define BT_APPEARANCE_GENERIC_REMOTE 0x0180 +/** Generic Eye-glasses */ +#define BT_APPEARANCE_GENERIC_EYEGLASSES 0x01C0 +/** Generic Tag */ +#define BT_APPEARANCE_GENERIC_TAG 0x0200 +/** Generic Keyring */ +#define BT_APPEARANCE_GENERIC_KEYRING 0x0240 +/** Generic Media Player */ +#define BT_APPEARANCE_GENERIC_MEDIA_PLAYER 0x0280 +/** Generic Barcode Scanner */ +#define BT_APPEARANCE_GENERIC_BARCODE_SCANNER 0x02C0 +/** Generic Thermometer */ +#define BT_APPEARANCE_GENERIC_THERMOMETER 0x0300 +/** Ear Thermometer */ +#define BT_APPEARANCE_THERMOMETER_EAR 0x0301 +/** Generic Heart Rate Sensor */ +#define BT_APPEARANCE_GENERIC_HEART_RATE 0x0340 +/** Heart Rate Belt */ +#define BT_APPEARANCE_HEART_RATE_BELT 0x0341 +/** Generic Blood Pressure */ +#define BT_APPEARANCE_GENERIC_BLOOD_PRESSURE 0x0380 +/** Arm Blood Pressure */ +#define BT_APPEARANCE_BLOOD_PRESSURE_ARM 0x0381 +/** Wrist Blood Pressure */ +#define BT_APPEARANCE_BLOOD_PRESSURE_WRIST 0x0382 +/** Generic Human Interface Device */ +#define BT_APPEARANCE_GENERIC_HID 0x03C0 +/** Keyboard */ +#define BT_APPEARANCE_HID_KEYBOARD 0x03C1 +/** Mouse */ +#define BT_APPEARANCE_HID_MOUSE 0x03C2 +/** Joystick */ +#define BT_APPEARANCE_HID_JOYSTICK 0x03C3 +/** Gamepad */ +#define BT_APPEARANCE_HID_GAMEPAD 0x03C4 +/** Digitizer Tablet */ +#define BT_APPEARANCE_HID_DIGITIZER_TABLET 0x03C5 +/** Card Reader */ +#define BT_APPEARANCE_HID_CARD_READER 0x03C6 +/** Digital Pen */ +#define BT_APPEARANCE_HID_DIGITAL_PEN 0x03C7 +/** Barcode Scanner */ +#define BT_APPEARANCE_HID_BARCODE_SCANNER 0x03C8 +/** Touchpad */ +#define BT_APPEARANCE_HID_TOUCHPAD 0x03C9 +/** Presentation Remote */ +#define BT_APPEARANCE_HID_PRESENTATION_REMOTE 0x03CA +/** Generic Glucose Meter */ +#define BT_APPEARANCE_GENERIC_GLUCOSE 0x0400 +/** Generic Running Walking Sensor */ +#define BT_APPEARANCE_GENERIC_WALKING 0x0440 +/** In-Shoe Running Walking Sensor */ +#define BT_APPEARANCE_WALKING_IN_SHOE 0x0441 +/** On-Shoe Running Walking Sensor */ +#define BT_APPEARANCE_WALKING_ON_SHOE 0x0442 +/** On-Hip Running Walking Sensor */ +#define BT_APPEARANCE_WALKING_ON_HIP 0x0443 +/** Generic Cycling */ +#define BT_APPEARANCE_GENERIC_CYCLING 0x0480 +/** Cycling Computer */ +#define BT_APPEARANCE_CYCLING_COMPUTER 0x0481 +/** Speed Sensor */ +#define BT_APPEARANCE_CYCLING_SPEED 0x0482 +/** Cadence Sensor */ +#define BT_APPEARANCE_CYCLING_CADENCE 0x0483 +/** Power Sensor */ +#define BT_APPEARANCE_CYCLING_POWER 0x0484 +/** Speed and Cadence Sensor */ +#define BT_APPEARANCE_CYCLING_SPEED_CADENCE 0x0485 +/** Generic Control Device */ +#define BT_APPEARANCE_GENERIC_CONTROL_DEVICE 0x04C0 +/** Switch */ +#define BT_APPEARANCE_CONTROL_SWITCH 0x04C1 +/** Multi-switch */ +#define BT_APPEARANCE_CONTROL_MULTI_SWITCH 0x04C2 +/** Button */ +#define BT_APPEARANCE_CONTROL_BUTTON 0x04C3 +/** Slider */ +#define BT_APPEARANCE_CONTROL_SLIDER 0x04C4 +/** Rotary Switch */ +#define BT_APPEARANCE_CONTROL_ROTARY_SWITCH 0x04C5 +/** Touch Panel */ +#define BT_APPEARANCE_CONTROL_TOUCH_PANEL 0x04C6 +/** Single Switch */ +#define BT_APPEARANCE_CONTROL_SINGLE_SWITCH 0x04C7 +/** Double Switch */ +#define BT_APPEARANCE_CONTROL_DOUBLE_SWITCH 0x04C8 +/** Triple Switch */ +#define BT_APPEARANCE_CONTROL_TRIPLE_SWITCH 0x04C9 +/** Battery Switch */ +#define BT_APPEARANCE_CONTROL_BATTERY_SWITCH 0x04CA +/** Energy Harvesting Switch */ +#define BT_APPEARANCE_CONTROL_ENERGY_HARVESTING_SWITCH 0x04CB +/** Push Button */ +#define BT_APPEARANCE_CONTROL_PUSH_BUTTON 0x04CC +/** Generic Network Device */ +#define BT_APPEARANCE_GENERIC_NETWORK_DEVICE 0x0500 +/** Access Point */ +#define BT_APPEARANCE_NETWORK_ACCESS_POINT 0x0501 +/** Mesh Device */ +#define BT_APPEARANCE_NETWORK_MESH_DEVICE 0x0502 +/** Mesh Network Proxy */ +#define BT_APPEARANCE_NETWORK_MESH_PROXY 0x0503 +/** Generic Sensor */ +#define BT_APPEARANCE_GENERIC_SENSOR 0x0540 +/** Motion Sensor */ +#define BT_APPEARANCE_SENSOR_MOTION 0x0541 +/** Air quality Sensor */ +#define BT_APPEARANCE_SENSOR_AIR_QUALITY 0x0542 +/** Temperature Sensor */ +#define BT_APPEARANCE_SENSOR_TEMPERATURE 0x0543 +/** Humidity Sensor */ +#define BT_APPEARANCE_SENSOR_HUMIDITY 0x0544 +/** Leak Sensor */ +#define BT_APPEARANCE_SENSOR_LEAK 0x0545 +/** Smoke Sensor */ +#define BT_APPEARANCE_SENSOR_SMOKE 0x0546 +/** Occupancy Sensor */ +#define BT_APPEARANCE_SENSOR_OCCUPANCY 0x0547 +/** Contact Sensor */ +#define BT_APPEARANCE_SENSOR_CONTACT 0x0548 +/** Carbon Monoxide Sensor */ +#define BT_APPEARANCE_SENSOR_CARBON_MONOXIDE 0x0549 +/** Carbon Dioxide Sensor */ +#define BT_APPEARANCE_SENSOR_CARBON_DIOXIDE 0x054A +/** Ambient Light Sensor */ +#define BT_APPEARANCE_SENSOR_AMBIENT_LIGHT 0x054B +/** Energy Sensor */ +#define BT_APPEARANCE_SENSOR_ENERGY 0x054C +/** Color Light Sensor */ +#define BT_APPEARANCE_SENSOR_COLOR_LIGHT 0x054D +/** Rain Sensor */ +#define BT_APPEARANCE_SENSOR_RAIN 0x054E +/** Fire Sensor */ +#define BT_APPEARANCE_SENSOR_FIRE 0x054F +/** Wind Sensor */ +#define BT_APPEARANCE_SENSOR_WIND 0x0550 +/** Proximity Sensor */ +#define BT_APPEARANCE_SENSOR_PROXIMITY 0x0551 +/** Multi-Sensor */ +#define BT_APPEARANCE_SENSOR_MULTI 0x0552 +/** Flush Mounted Sensor */ +#define BT_APPEARANCE_SENSOR_FLUSH_MOUNTED 0x0553 +/** Ceiling Mounted Sensor */ +#define BT_APPEARANCE_SENSOR_CEILING_MOUNTED 0x0554 +/** Wall Mounted Sensor */ +#define BT_APPEARANCE_SENSOR_WALL_MOUNTED 0x0555 +/** Multisensor */ +#define BT_APPEARANCE_MULTISENSOR 0x0556 +/** Energy Meter */ +#define BT_APPEARANCE_SENSOR_ENERGY_METER 0x0557 +/** Flame Detector */ +#define BT_APPEARANCE_SENSOR_FLAME_DETECTOR 0x0558 +/** Vehicle Tire Pressure Sensor */ +#define BT_APPEARANCE_SENSOR_VEHICLE_TIRE_PRESSURE 0x0559 +/** Generic Light Fixtures */ +#define BT_APPEARANCE_GENERIC_LIGHT_FIXTURES 0x0580 +/** Wall Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_WALL 0x0581 +/** Ceiling Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_CEILING 0x0582 +/** Floor Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_FLOOR 0x0583 +/** Cabinet Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_CABINET 0x0584 +/** Desk Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_DESK 0x0585 +/** Troffer Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_TROFFER 0x0586 +/** Pendant Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_PENDANT 0x0587 +/** In-ground Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_IN_GROUND 0x0588 +/** Flood Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_FLOOD 0x0589 +/** Underwater Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_UNDERWATER 0x058A +/** Bollard with Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_BOLLARD_WITH 0x058B +/** Pathway Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_PATHWAY 0x058C +/** Garden Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_GARDEN 0x058D +/** Pole-top Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_POLE_TOP 0x058E +/** Spotlight */ +#define BT_APPEARANCE_SPOT_LIGHT 0x058F +/** Linear Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_LINEAR 0x0590 +/** Street Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_STREET 0x0591 +/** Shelves Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_SHELVES 0x0592 +/** Bay Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_BAY 0x0593 +/** Emergency Exit Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_EMERGENCY_EXIT 0x0594 +/** Light Controller */ +#define BT_APPEARANCE_LIGHT_FIXTURES_CONTROLLER 0x0595 +/** Light Driver */ +#define BT_APPEARANCE_LIGHT_FIXTURES_DRIVER 0x0596 +/** Bulb */ +#define BT_APPEARANCE_LIGHT_FIXTURES_BULB 0x0597 +/** Low-bay Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_LOW_BAY 0x0598 +/** High-bay Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_HIGH_BAY 0x0599 +/** Generic Fan */ +#define BT_APPEARANCE_GENERIC_FAN 0x05C0 +/** Ceiling Fan */ +#define BT_APPEARANCE_FAN_CEILING 0x05C1 +/** Axial Fan */ +#define BT_APPEARANCE_FAN_AXIAL 0x05C2 +/** Exhaust Fan */ +#define BT_APPEARANCE_FAN_EXHAUST 0x05C3 +/** Pedestal Fan */ +#define BT_APPEARANCE_FAN_PEDESTAL 0x05C4 +/** Desk Fan */ +#define BT_APPEARANCE_FAN_DESK 0x05C5 +/** Wall Fan */ +#define BT_APPEARANCE_FAN_WALL 0x05C6 +/** Generic HVAC */ +#define BT_APPEARANCE_GENERIC_HVAC 0x0600 +/** Thermostat */ +#define BT_APPEARANCE_HVAC_THERMOSTAT 0x0601 +/** Humidifier */ +#define BT_APPEARANCE_HVAC_HUMIDIFIER 0x0602 +/** De-humidifier */ +#define BT_APPEARANCE_HVAC_DEHUMIDIFIER 0x0603 +/** Heater */ +#define BT_APPEARANCE_HVAC_HEATER 0x0604 +/** Radiator */ +#define BT_APPEARANCE_HVAC_RADIATOR 0x0605 +/** Boiler */ +#define BT_APPEARANCE_HVAC_BOILER 0x0606 +/** Heat Pump */ +#define BT_APPEARANCE_HVAC_HEAT_PUMP 0x0607 +/** Infrared Heater */ +#define BT_APPEARANCE_HVAC_INFRARED_HEATER 0x0608 +/** Radiant Panel Heater */ +#define BT_APPEARANCE_HVAC_RADIANT_PANEL_HEATER 0x0609 +/** Fan Heater */ +#define BT_APPEARANCE_HVAC_FAN_HEATER 0x060A +/** Air Curtain */ +#define BT_APPEARANCE_HVAC_AIR_CURTAIN 0x060B +/** Generic Air Conditioning */ +#define BT_APPEARANCE_GENERIC_AIR_CONDITIONING 0x0640 +/** Generic Humidifier */ +#define BT_APPEARANCE_GENERIC_HUMIDIFIER 0x0680 +/** Generic Heating */ +#define BT_APPEARANCE_GENERIC_HEATING 0x06C0 +/** Radiator */ +#define BT_APPEARANCE_HEATING_RADIATOR 0x06C1 +/** Boiler */ +#define BT_APPEARANCE_HEATING_BOILER 0x06C2 +/** Heat Pump */ +#define BT_APPEARANCE_HEATING_HEAT_PUMP 0x06C3 +/** Infrared Heater */ +#define BT_APPEARANCE_HEATING_INFRARED_HEATER 0x06C4 +/** Radiant Panel Heater */ +#define BT_APPEARANCE_HEATING_RADIANT_PANEL_HEATER 0x06C5 +/** Fan Heater */ +#define BT_APPEARANCE_HEATING_FAN_HEATER 0x06C6 +/** Air Curtain */ +#define BT_APPEARANCE_HEATING_AIR_CURTAIN 0x06C7 +/** Generic Access Control */ +#define BT_APPEARANCE_GENERIC_ACCESS_CONTROL 0x0700 +/** Access Door */ +#define BT_APPEARANCE_CONTROL_ACCESS_DOOR 0x0701 +/** Garage Door */ +#define BT_APPEARANCE_CONTROL_GARAGE_DOOR 0x0702 +/** Emergency Exit Door */ +#define BT_APPEARANCE_CONTROL_EMERGENCY_EXIT_DOOR 0x0703 +/** Access Lock */ +#define BT_APPEARANCE_CONTROL_ACCESS_LOCK 0x0704 +/** Elevator */ +#define BT_APPEARANCE_CONTROL_ELEVATOR 0x0705 +/** Window */ +#define BT_APPEARANCE_CONTROL_WINDOW 0x0706 +/** Entrance Gate */ +#define BT_APPEARANCE_CONTROL_ENTRANCE_GATE 0x0707 +/** Door Lock */ +#define BT_APPEARANCE_CONTROL_DOOR_LOCK 0x0708 +/** Locker */ +#define BT_APPEARANCE_CONTROL_LOCKER 0x0709 +/** Generic Motorized Device */ +#define BT_APPEARANCE_GENERIC_MOTORIZED_DEVICE 0x0740 +/** Motorized Gate */ +#define BT_APPEARANCE_MOTORIZED_GATE 0x0741 +/** Awning */ +#define BT_APPEARANCE_MOTORIZED_AWNING 0x0742 +/** Blinds or Shades */ +#define BT_APPEARANCE_MOTORIZED_BLINDS_OR_SHADES 0x0743 +/** Curtains */ +#define BT_APPEARANCE_MOTORIZED_CURTAINS 0x0744 +/** Screen */ +#define BT_APPEARANCE_MOTORIZED_SCREEN 0x0745 +/** Generic Power Device */ +#define BT_APPEARANCE_GENERIC_POWER_DEVICE 0x0780 +/** Power Outlet */ +#define BT_APPEARANCE_POWER_OUTLET 0x0781 +/** Power Strip */ +#define BT_APPEARANCE_POWER_STRIP 0x0782 +/** Plug */ +#define BT_APPEARANCE_POWER_PLUG 0x0783 +/** Power Supply */ +#define BT_APPEARANCE_POWER_SUPPLY 0x0784 +/** LED Driver */ +#define BT_APPEARANCE_POWER_LED_DRIVER 0x0785 +/** Fluorescent Lamp Gear */ +#define BT_APPEARANCE_POWER_FLUORESCENT_LAMP_GEAR 0x0786 +/** HID Lamp Gear */ +#define BT_APPEARANCE_POWER_HID_LAMP_GEAR 0x0787 +/** Charge Case */ +#define BT_APPEARANCE_POWER_CHARGE_CASE 0x0788 +/** Power Bank */ +#define BT_APPEARANCE_POWER_POWER_BANK 0x0789 +/** Generic Light Source */ +#define BT_APPEARANCE_GENERIC_LIGHT_SOURCE 0x07C0 +/** Incandescent Light Bulb */ +#define BT_APPEARANCE_LIGHT_SOURCE_INCANDESCENT_BULB 0x07C1 +/** LED Lamp */ +#define BT_APPEARANCE_LIGHT_SOURCE_LED_LAMP 0x07C2 +/** HID Lamp */ +#define BT_APPEARANCE_LIGHT_SOURCE_HID_LAMP 0x07C3 +/** Fluorescent Lamp */ +#define BT_APPEARANCE_LIGHT_SOURCE_FLUORESCENT_LAMP 0x07C4 +/** LED Array */ +#define BT_APPEARANCE_LIGHT_SOURCE_LED_ARRAY 0x07C5 +/** Multi-Color LED Array */ +#define BT_APPEARANCE_LIGHT_SOURCE_MULTICOLOR_LED_ARRAY 0x07C6 +/** Low voltage halogen */ +#define BT_APPEARANCE_LIGHT_SOURCE_LOW_VOLTAGE_HALOGEN 0x07C7 +/** Organic light emitting diode */ +#define BT_APPEARANCE_LIGHT_SOURCE_OLED 0x07C8 +/** Generic Window Covering */ +#define BT_APPEARANCE_GENERIC_WINDOW_COVERING 0x0800 +/** Window Shades */ +#define BT_APPEARANCE_WINDOW_SHADES 0x0801 +/** Window Blinds */ +#define BT_APPEARANCE_WINDOW_BLINDS 0x0802 +/** Window Awning */ +#define BT_APPEARANCE_WINDOW_AWNING 0x0803 +/** Window Curtain */ +#define BT_APPEARANCE_WINDOW_CURTAIN 0x0804 +/** Exterior Shutter */ +#define BT_APPEARANCE_WINDOW_EXTERIOR_SHUTTER 0x0805 +/** Exterior Screen */ +#define BT_APPEARANCE_WINDOW_EXTERIOR_SCREEN 0x0806 +/** Generic Audio Sink */ +#define BT_APPEARANCE_GENERIC_AUDIO_SINK 0x0840 +/** Standalone Speaker */ +#define BT_APPEARANCE_AUDIO_SINK_STANDALONE_SPEAKER 0x0841 +/** Soundbar */ +#define BT_APPEARANCE_AUDIO_SINK_SOUNDBAR 0x0842 +/** Bookshelf Speaker */ +#define BT_APPEARANCE_AUDIO_SINK_BOOKSHELF_SPEAKER 0x0843 +/** Standmounted Speaker */ +#define BT_APPEARANCE_AUDIO_SINK_STANDMOUNTED_SPEAKER 0x0844 +/** Speakerphone */ +#define BT_APPEARANCE_AUDIO_SINK_SPEAKERPHONE 0x0845 +/** Generic Audio Source */ +#define BT_APPEARANCE_GENERIC_AUDIO_SOURCE 0x0880 +/** Microphone */ +#define BT_APPEARANCE_AUDIO_SOURCE_MICROPHONE 0x0881 +/** Alarm */ +#define BT_APPEARANCE_AUDIO_SOURCE_ALARM 0x0882 +/** Bell */ +#define BT_APPEARANCE_AUDIO_SOURCE_BELL 0x0883 +/** Horn */ +#define BT_APPEARANCE_AUDIO_SOURCE_HORN 0x0884 +/** Broadcasting Device */ +#define BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE 0x0885 +/** Service Desk */ +#define BT_APPEARANCE_AUDIO_SOURCE_SERVICE_DESK 0x0886 +/** Kiosk */ +#define BT_APPEARANCE_AUDIO_SOURCE_KIOSK 0x0887 +/** Broadcasting Room */ +#define BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_ROOM 0x0888 +/** Auditorium */ +#define BT_APPEARANCE_AUDIO_SOURCE_AUDITORIUM 0x0889 +/** Generic Motorized Vehicle */ +#define BT_APPEARANCE_GENERIC_MOTORIZED_VEHICLE 0x08C0 +/** Car */ +#define BT_APPEARANCE_VEHICLE_CAR 0x08C1 +/** Large Goods Vehicle */ +#define BT_APPEARANCE_VEHICLE_LARGE_GOODS 0x08C2 +/** 2-Wheeled Vehicle */ +#define BT_APPEARANCE_VEHICLE_TWO_WHEELED 0x08C3 +/** Motorbike */ +#define BT_APPEARANCE_VEHICLE_MOTORBIKE 0x08C4 +/** Scooter */ +#define BT_APPEARANCE_VEHICLE_SCOOTER 0x08C5 +/** Moped */ +#define BT_APPEARANCE_VEHICLE_MOPED 0x08C6 +/** 3-Wheeled Vehicle */ +#define BT_APPEARANCE_VEHICLE_THREE_WHEELED 0x08C7 +/** Light Vehicle */ +#define BT_APPEARANCE_VEHICLE_LIGHT 0x08C8 +/** Quad Bike */ +#define BT_APPEARANCE_VEHICLE_QUAD_BIKE 0x08C9 +/** Minibus */ +#define BT_APPEARANCE_VEHICLE_MINIBUS 0x08CA +/** Bus */ +#define BT_APPEARANCE_VEHICLE_BUS 0x08CB +/** Trolley */ +#define BT_APPEARANCE_VEHICLE_TROLLEY 0x08CC +/** Agricultural Vehicle */ +#define BT_APPEARANCE_VEHICLE_AGRICULTURAL 0x08CD +/** Camper/Caravan */ +#define BT_APPEARANCE_VEHICLE_CAMPER_OR_CARAVAN 0x08CE +/** Recreational Vehicle/Motor Home */ +#define BT_APPEARANCE_VEHICLE_RECREATIONAL 0x08CF +/** Generic Domestic Appliance */ +#define BT_APPEARANCE_GENERIC_DOMESTIC_APPLIANCE 0x0900 +/** Refrigerator */ +#define BT_APPEARANCE_APPLIANCE_REFRIGERATOR 0x0901 +/** Freezer */ +#define BT_APPEARANCE_APPLIANCE_FREEZER 0x0902 +/** Oven */ +#define BT_APPEARANCE_APPLIANCE_OVEN 0x0903 +/** Microwave */ +#define BT_APPEARANCE_APPLIANCE_MICROWAVE 0x0904 +/** Toaster */ +#define BT_APPEARANCE_APPLIANCE_TOASTER 0x0905 +/** Washing Machine */ +#define BT_APPEARANCE_APPLIANCE_WASHING_MACHINE 0x0906 +/** Dryer */ +#define BT_APPEARANCE_APPLIANCE_DRYER 0x0907 +/** Coffee maker */ +#define BT_APPEARANCE_APPLIANCE_COFFEE_MAKER 0x0908 +/** Clothes iron */ +#define BT_APPEARANCE_APPLIANCE_CLOTHES_IRON 0x0909 +/** Curling iron */ +#define BT_APPEARANCE_APPLIANCE_CURLING_IRON 0x090A +/** Hair dryer */ +#define BT_APPEARANCE_APPLIANCE_HAIR_DRYER 0x090B +/** Vacuum cleaner */ +#define BT_APPEARANCE_APPLIANCE_VACUUM_CLEANER 0x090C +/** Robotic vacuum cleaner */ +#define BT_APPEARANCE_APPLIANCE_ROBOTIC_VACUUM_CLEANER 0x090D +/** Rice cooker */ +#define BT_APPEARANCE_APPLIANCE_RICE_COOKER 0x090E +/** Clothes steamer */ +#define BT_APPEARANCE_APPLIANCE_CLOTHES_STEAMER 0x090F +/** Generic Wearable Audio Device */ +#define BT_APPEARANCE_GENERIC_WEARABLE_AUDIO_DEVICE 0x0940 +/** Earbud */ +#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_EARBUD 0x0941 +/** Headset */ +#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADSET 0x0942 +/** Headphones */ +#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADPHONES 0x0943 +/** Neck Band */ +#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_NECK_BAND 0x0944 +/** Generic Aircraft */ +#define BT_APPEARANCE_GENERIC_AIRCRAFT 0x0980 +/** Light Aircraft */ +#define BT_APPEARANCE_AIRCRAFT_LIGHT 0x0981 +/** Microlight */ +#define BT_APPEARANCE_AIRCRAFT_MICROLIGHT 0x0982 +/** Paraglider */ +#define BT_APPEARANCE_AIRCRAFT_PARAGLIDER 0x0983 +/** Large Passenger Aircraft */ +#define BT_APPEARANCE_AIRCRAFT_LARGE_PASSENGER 0x0984 +/** Generic AV Equipment */ +#define BT_APPEARANCE_GENERIC_AV_EQUIPMENT 0x09C0 +/** Amplifier */ +#define BT_APPEARANCE_AV_EQUIPMENT_AMPLIFIER 0x09C1 +/** Receiver */ +#define BT_APPEARANCE_AV_EQUIPMENT_RECEIVER 0x09C2 +/** Radio */ +#define BT_APPEARANCE_AV_EQUIPMENT_RADIO 0x09C3 +/** Tuner */ +#define BT_APPEARANCE_AV_EQUIPMENT_TUNER 0x09C4 +/** Turntable */ +#define BT_APPEARANCE_AV_EQUIPMENT_TURNTABLE 0x09C5 +/** CD Player */ +#define BT_APPEARANCE_AV_EQUIPMENT_CD_PLAYER 0x09C6 +/** DVD Player */ +#define BT_APPEARANCE_AV_EQUIPMENT_DVD_PLAYER 0x09C7 +/** Bluray Player */ +#define BT_APPEARANCE_AV_EQUIPMENT_BLURAY_PLAYER 0x09C8 +/** Optical Disc Player */ +#define BT_APPEARANCE_AV_EQUIPMENT_OPTICAL_DISC_PLAYER 0x09C9 +/** Set-Top Box */ +#define BT_APPEARANCE_AV_EQUIPMENT_SET_TOP_BOX 0x09CA +/** Generic Display Equipment */ +#define BT_APPEARANCE_GENERIC_DISPLAY_EQUIPMENT 0x0A00 +/** Television */ +#define BT_APPEARANCE_DISPLAY_EQUIPMENT_TELEVISION 0x0A01 +/** Monitor */ +#define BT_APPEARANCE_DISPLAY_EQUIPMENT_MONITOR 0x0A02 +/** Projector */ +#define BT_APPEARANCE_DISPLAY_EQUIPMENT_PROJECTOR 0x0A03 +/** Generic Hearing aid */ +#define BT_APPEARANCE_GENERIC_HEARING_AID 0x0A40 +/** In-ear hearing aid */ +#define BT_APPEARANCE_HEARING_AID_IN_EAR 0x0A41 +/** Behind-ear hearing aid */ +#define BT_APPEARANCE_HEARING_AID_BEHIND_EAR 0x0A42 +/** Cochlear Implant */ +#define BT_APPEARANCE_HEARING_AID_COCHLEAR_IMPLANT 0x0A43 +/** Generic Gaming */ +#define BT_APPEARANCE_GENERIC_GAMING 0x0A80 +/** Home Video Game Console */ +#define BT_APPEARANCE_HOME_VIDEO_GAME_CONSOLE 0x0A81 +/** Portable handheld console */ +#define BT_APPEARANCE_PORTABLE_HANDHELD_CONSOLE 0x0A82 +/** Generic Signage */ +#define BT_APPEARANCE_GENERIC_SIGNAGE 0x0AC0 +/** Digital Signage */ +#define BT_APPEARANCE_SIGNAGE_DIGITAL 0x0AC1 +/** Electronic Label */ +#define BT_APPEARANCE_SIGNAGE_ELECTRONIC_LABEL 0x0AC2 +/** Generic Pulse Oximeter */ +#define BT_APPEARANCE_GENERIC_PULSE_OXIMETER 0x0C40 +/** Fingertip Pulse Oximeter */ +#define BT_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41 +/** Wrist Worn Pulse Oximeter */ +#define BT_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42 +/** Generic Weight Scale */ +#define BT_APPEARANCE_GENERIC_WEIGHT_SCALE 0x0C80 +/** Generic Personal Mobility Device */ +#define BT_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE 0x0CC0 +/** Powered Wheelchair */ +#define BT_APPEARANCE_MOBILITY_POWERED_WHEELCHAIR 0x0CC1 +/** Mobility Scooter */ +#define BT_APPEARANCE_MOBILITY_SCOOTER 0x0CC2 +/** Continuous Glucose Monitor */ +#define BT_APPEARANCE_CONTINUOUS_GLUCOSE_MONITOR 0x0D00 +/** Generic Insulin Pump */ +#define BT_APPEARANCE_GENERIC_INSULIN_PUMP 0x0D40 +/** Insulin Pump, durable pump */ +#define BT_APPEARANCE_INSULIN_PUMP_DURABLE 0x0D41 +/** Insulin Pump, patch pump */ +#define BT_APPEARANCE_INSULIN_PUMP_PATCH 0x0D44 +/** Insulin Pen */ +#define BT_APPEARANCE_INSULIN_PEN 0x0D48 +/** Generic Medication Delivery */ +#define BT_APPEARANCE_GENERIC_MEDICATION_DELIVERY 0x0D80 +/** Generic Spirometer */ +#define BT_APPEARANCE_GENERIC_SPIROMETER 0x0DC0 +/** Handheld Spirometer */ +#define BT_APPEARANCE_SPIROMETER_HANDHELD 0x0DC1 +/** Generic Outdoor Sports Activity */ +#define BT_APPEARANCE_GENERIC_OUTDOOR_SPORTS 0x1440 +/** Location Display */ +#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION 0x1441 +/** Location and Navigation Display */ +#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV 0x1442 +/** Location Pod */ +#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD 0x1443 +/** Location and Navigation Pod */ +#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV 0x1444 + +/** @} */ /* end of @name Appearance Numbers */ + +/** + * @name Common Data Types + * @{ + */ +#define BT_DATA_FLAGS 0x01 /**< AD flags */ +#define BT_DATA_UUID16_SOME 0x02 /**< 16-bit UUID, more available */ +#define BT_DATA_UUID16_ALL 0x03 /**< 16-bit UUID, all listed */ +#define BT_DATA_UUID32_SOME 0x04 /**< 32-bit UUID, more available */ +#define BT_DATA_UUID32_ALL 0x05 /**< 32-bit UUID, all listed */ +#define BT_DATA_UUID128_SOME 0x06 /**< 128-bit UUID, more available */ +#define BT_DATA_UUID128_ALL 0x07 /**< 128-bit UUID, all listed */ +#define BT_DATA_NAME_SHORTENED 0x08 /**< Shortened name */ +#define BT_DATA_NAME_COMPLETE 0x09 /**< Complete name */ +#define BT_DATA_TX_POWER 0x0a /**< Tx Power */ +#define BT_DATA_DEVICE_CLASS 0x0d /**< Class of Device */ +#define BT_DATA_SIMPLE_PAIRING_HASH_C192 0x0e /**< Simple Pairing Hash C-192 */ +#define BT_DATA_SIMPLE_PAIRING_RAND_C192 0x0f /**< Simple Pairing Randomizer R-192 */ +#define BT_DATA_DEVICE_ID 0x10 /**< Device ID (Profile) */ +#define BT_DATA_SM_TK_VALUE 0x10 /**< Security Manager TK Value */ +#define BT_DATA_SM_OOB_FLAGS 0x11 /**< Security Manager OOB Flags */ +#define BT_DATA_PERIPHERAL_INT_RANGE 0x12 /**< Peripheral Connection Interval Range */ +#define BT_DATA_SOLICIT16 0x14 /**< Solicit UUIDs, 16-bit */ +#define BT_DATA_SOLICIT128 0x15 /**< Solicit UUIDs, 128-bit */ +#define BT_DATA_SVC_DATA16 0x16 /**< Service data, 16-bit UUID */ +#define BT_DATA_PUB_TARGET_ADDR 0x17 /**< Public Target Address */ +#define BT_DATA_RAND_TARGET_ADDR 0x18 /**< Random Target Address */ +#define BT_DATA_GAP_APPEARANCE 0x19 /**< GAP appearance */ +#define BT_DATA_ADV_INT 0x1a /**< Advertising Interval */ +#define BT_DATA_LE_BT_DEVICE_ADDRESS 0x1b /**< LE Bluetooth Device Address */ +#define BT_DATA_LE_ROLE 0x1c /**< LE Role */ +#define BT_DATA_SIMPLE_PAIRING_HASH 0x1d /**< Simple Pairing Hash C256 */ +#define BT_DATA_SIMPLE_PAIRING_RAND 0x1e /**< Simple Pairing Randomizer R256 */ +#define BT_DATA_SOLICIT32 0x1f /**< Solicit UUIDs, 32-bit */ +#define BT_DATA_SVC_DATA32 0x20 /**< Service data, 32-bit UUID */ +#define BT_DATA_SVC_DATA128 0x21 /**< Service data, 128-bit UUID */ +#define BT_DATA_LE_SC_CONFIRM_VALUE 0x22 /**< LE SC Confirmation Value */ +#define BT_DATA_LE_SC_RANDOM_VALUE 0x23 /**< LE SC Random Value */ +#define BT_DATA_URI 0x24 /**< URI */ +#define BT_DATA_INDOOR_POS 0x25 /**< Indoor Positioning */ +#define BT_DATA_TRANS_DISCOVER_DATA 0x26 /**< Transport Discovery Data */ +#define BT_DATA_LE_SUPPORTED_FEATURES 0x27 /**< LE Supported Features */ +#define BT_DATA_CHANNEL_MAP_UPDATE_IND 0x28 /**< Channel Map Update Indication */ +#define BT_DATA_MESH_PROV 0x29 /**< Mesh Provisioning PDU */ +#define BT_DATA_MESH_MESSAGE 0x2a /**< Mesh Networking PDU */ +#define BT_DATA_MESH_BEACON 0x2b /**< Mesh Beacon */ +#define BT_DATA_BIG_INFO 0x2c /**< BIGInfo */ +#define BT_DATA_BROADCAST_CODE 0x2d /**< Broadcast Code */ +#define BT_DATA_CSIS_RSI 0x2e /**< CSIS Random Set ID type */ +#define BT_DATA_ADV_INT_LONG 0x2f /**< Advertising Interval long */ +#define BT_DATA_BROADCAST_NAME 0x30 /**< Broadcast Name */ +#define BT_DATA_ENCRYPTED_AD_DATA 0x31 /**< Encrypted Advertising Data */ +#define BT_DATA_PAWR_TIMING_INFO 0x32 /**< Periodic Advertising Response Timing Info */ +#define BT_DATA_ESL 0x34 /**< Electronic Shelf Label Profile */ +#define BT_DATA_3D_INFO 0x3D /**< 3D Information Data */ + +#define BT_DATA_MANUFACTURER_DATA 0xff /**< Manufacturer Specific Data */ + +/** @} */ /* end of @name Common Data Types */ + +/** + * @name Flags data type values + * @{ + */ + +#define BT_LE_AD_LIMITED 0x01 /**< Limited Discoverable */ +#define BT_LE_AD_GENERAL 0x02 /**< General Discoverable */ +#define BT_LE_AD_NO_BREDR 0x04 /**< BR/EDR not supported */ + +/** @} */ /* end of @name Flags data type values */ +/** @} */ /* end of bt_assigned_numbers_core */ + +/** + * @brief Bluetooth Mesh Assigned Numbers + * @defgroup bt_assigned_numbers_mesh Bluetooth Mesh Assigned Numbers + * @ingroup bt_assigned_numbers + * @{ + */ + +/** + * @name Foundation Models + * @{ + */ +/** Configuration Server */ +#define BT_MESH_MODEL_ID_CFG_SRV 0x0000 +/** Configuration Client */ +#define BT_MESH_MODEL_ID_CFG_CLI 0x0001 +/** Health Server */ +#define BT_MESH_MODEL_ID_HEALTH_SRV 0x0002 +/** Health Client */ +#define BT_MESH_MODEL_ID_HEALTH_CLI 0x0003 +/** Remote Provisioning Server */ +#define BT_MESH_MODEL_ID_REMOTE_PROV_SRV 0x0004 +/** Remote Provisioning Client */ +#define BT_MESH_MODEL_ID_REMOTE_PROV_CLI 0x0005 +/** Bridge Configuration Sever */ +#define BT_MESH_MODEL_ID_BRG_CFG_SRV 0x0008 +/** Bridge Configuration Client */ +#define BT_MESH_MODEL_ID_BRG_CFG_CLI 0x0009 +/** Private Beacon Server */ +#define BT_MESH_MODEL_ID_PRIV_BEACON_SRV 0x000a +/** Private Beacon Client */ +#define BT_MESH_MODEL_ID_PRIV_BEACON_CLI 0x000b +/** SAR Configuration Server */ +#define BT_MESH_MODEL_ID_SAR_CFG_SRV 0x000e +/** SAR Configuration Client */ +#define BT_MESH_MODEL_ID_SAR_CFG_CLI 0x000f +/** Opcodes Aggregator Server */ +#define BT_MESH_MODEL_ID_OP_AGG_SRV 0x0010 +/** Opcodes Aggregator Client */ +#define BT_MESH_MODEL_ID_OP_AGG_CLI 0x0011 +/** Large Composition Data Server */ +#define BT_MESH_MODEL_ID_LARGE_COMP_DATA_SRV 0x0012 +/** Large Composition Data Client */ +#define BT_MESH_MODEL_ID_LARGE_COMP_DATA_CLI 0x0013 +/** Solicitation PDU RPL Configuration Client */ +#define BT_MESH_MODEL_ID_SOL_PDU_RPL_SRV 0x0014 +/** Solicitation PDU RPL Configuration Server */ +#define BT_MESH_MODEL_ID_SOL_PDU_RPL_CLI 0x0015 +/** Private Proxy Server */ +#define BT_MESH_MODEL_ID_ON_DEMAND_PROXY_SRV 0x000c +/** Private Proxy Client */ +#define BT_MESH_MODEL_ID_ON_DEMAND_PROXY_CLI 0x000d +/** + * @} + */ + +/** + * @name Models from the Mesh Model Specification + * @{ + */ +/** Generic OnOff Server */ +#define BT_MESH_MODEL_ID_GEN_ONOFF_SRV 0x1000 +/** Generic OnOff Client */ +#define BT_MESH_MODEL_ID_GEN_ONOFF_CLI 0x1001 +/** Generic Level Server */ +#define BT_MESH_MODEL_ID_GEN_LEVEL_SRV 0x1002 +/** Generic Level Client */ +#define BT_MESH_MODEL_ID_GEN_LEVEL_CLI 0x1003 +/** Generic Default Transition Time Server */ +#define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV 0x1004 +/** Generic Default Transition Time Client */ +#define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI 0x1005 +/** Generic Power OnOff Server */ +#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV 0x1006 +/** Generic Power OnOff Setup Server */ +#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV 0x1007 +/** Generic Power OnOff Client */ +#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI 0x1008 +/** Generic Power Level Server */ +#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV 0x1009 +/** Generic Power Level Setup Server */ +#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV 0x100a +/** Generic Power Level Client */ +#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_CLI 0x100b +/** Generic Battery Server */ +#define BT_MESH_MODEL_ID_GEN_BATTERY_SRV 0x100c +/** Generic Battery Client */ +#define BT_MESH_MODEL_ID_GEN_BATTERY_CLI 0x100d +/** Generic Location Server */ +#define BT_MESH_MODEL_ID_GEN_LOCATION_SRV 0x100e +/** Generic Location Setup Server */ +#define BT_MESH_MODEL_ID_GEN_LOCATION_SETUPSRV 0x100f +/** Generic Location Client */ +#define BT_MESH_MODEL_ID_GEN_LOCATION_CLI 0x1010 +/** Generic Admin Property Server */ +#define BT_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV 0x1011 +/** Generic Manufacturer Property Server */ +#define BT_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV 0x1012 +/** Generic User Property Server */ +#define BT_MESH_MODEL_ID_GEN_USER_PROP_SRV 0x1013 +/** Generic Client Property Server */ +#define BT_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV 0x1014 +/** Generic Property Client */ +#define BT_MESH_MODEL_ID_GEN_PROP_CLI 0x1015 +/** Sensor Server */ +#define BT_MESH_MODEL_ID_SENSOR_SRV 0x1100 +/** Sensor Setup Server */ +#define BT_MESH_MODEL_ID_SENSOR_SETUP_SRV 0x1101 +/** Sensor Client */ +#define BT_MESH_MODEL_ID_SENSOR_CLI 0x1102 +/** Time Server */ +#define BT_MESH_MODEL_ID_TIME_SRV 0x1200 +/** Time Setup Server */ +#define BT_MESH_MODEL_ID_TIME_SETUP_SRV 0x1201 +/** Time Client */ +#define BT_MESH_MODEL_ID_TIME_CLI 0x1202 +/** Scene Server */ +#define BT_MESH_MODEL_ID_SCENE_SRV 0x1203 +/** Scene Setup Server */ +#define BT_MESH_MODEL_ID_SCENE_SETUP_SRV 0x1204 +/** Scene Client */ +#define BT_MESH_MODEL_ID_SCENE_CLI 0x1205 +/** Scheduler Server */ +#define BT_MESH_MODEL_ID_SCHEDULER_SRV 0x1206 +/** Scheduler Setup Server */ +#define BT_MESH_MODEL_ID_SCHEDULER_SETUP_SRV 0x1207 +/** Scheduler Client */ +#define BT_MESH_MODEL_ID_SCHEDULER_CLI 0x1208 +/** Light Lightness Server */ +#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV 0x1300 +/** Light Lightness Setup Server */ +#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV 0x1301 +/** Light Lightness Client */ +#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI 0x1302 +/** Light CTL Server */ +#define BT_MESH_MODEL_ID_LIGHT_CTL_SRV 0x1303 +/** Light CTL Setup Server */ +#define BT_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV 0x1304 +/** Light CTL Client */ +#define BT_MESH_MODEL_ID_LIGHT_CTL_CLI 0x1305 +/** Light CTL Temperature Server */ +#define BT_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV 0x1306 +/** Light HSL Server */ +#define BT_MESH_MODEL_ID_LIGHT_HSL_SRV 0x1307 +/** Light HSL Setup Server */ +#define BT_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV 0x1308 +/** Light HSL Client */ +#define BT_MESH_MODEL_ID_LIGHT_HSL_CLI 0x1309 +/** Light HSL Hue Server */ +#define BT_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV 0x130a +/** Light HSL Saturation Server */ +#define BT_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV 0x130b +/** Light xyL Server */ +#define BT_MESH_MODEL_ID_LIGHT_XYL_SRV 0x130c +/** Light xyL Setup Server */ +#define BT_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV 0x130d +/** Light xyL Client */ +#define BT_MESH_MODEL_ID_LIGHT_XYL_CLI 0x130e +/** Light LC Server */ +#define BT_MESH_MODEL_ID_LIGHT_LC_SRV 0x130f +/** Light LC Setup Server */ +#define BT_MESH_MODEL_ID_LIGHT_LC_SETUPSRV 0x1310 +/** Light LC Client */ +#define BT_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311 +/** + * @} + */ + +/** + * @name Models from the Mesh Binary Large Object Transfer Model Specification + * @{ + */ +/** BLOB Transfer Server */ +#define BT_MESH_MODEL_ID_BLOB_SRV 0x1400 +/** BLOB Transfer Client */ +#define BT_MESH_MODEL_ID_BLOB_CLI 0x1401 +/** + * @} + */ + +/** + * @name Models from the Mesh Device Firmware Update Model Specification + * @{ + */ +/** Firmware Update Server */ +#define BT_MESH_MODEL_ID_DFU_SRV 0x1402 +/** Firmware Update Client */ +#define BT_MESH_MODEL_ID_DFU_CLI 0x1403 +/** Firmware Distribution Server */ +#define BT_MESH_MODEL_ID_DFD_SRV 0x1404 +/** Firmware Distribution Client */ +#define BT_MESH_MODEL_ID_DFD_CLI 0x1405 +/** + * @} + */ + +/** @} */ /* end of bt_assigned_numbers_mesh */ + +/** + * @brief Generic Audio Assigned Numbers + * @defgroup bt_assigned_numbers_audio Generic Audio Assigned Numbers + * @ingroup bt_assigned_numbers + * @{ + */ + +/** + * @brief Codec capability types + * + * Used to build and parse codec capabilities as specified in the PAC specification. + * Source is assigned numbers for Generic Audio, bluetooth.com. + */ +enum bt_audio_codec_cap_type { + /** Supported sampling frequencies */ + BT_AUDIO_CODEC_CAP_TYPE_FREQ = 0x01, + + /** Supported frame durations */ + BT_AUDIO_CODEC_CAP_TYPE_DURATION = 0x02, + + /** Supported audio channel counts */ + BT_AUDIO_CODEC_CAP_TYPE_CHAN_COUNT = 0x03, + + /** Supported octets per codec frame */ + BT_AUDIO_CODEC_CAP_TYPE_FRAME_LEN = 0x04, + + /** Supported maximum codec frames per SDU */ + BT_AUDIO_CODEC_CAP_TYPE_FRAME_COUNT = 0x05, +}; + +/** @brief Supported frequencies bitfield */ +enum bt_audio_codec_cap_freq { + /** 8 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_8KHZ = BIT(0), + + /** 11.025 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_11KHZ = BIT(1), + + /** 16 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_16KHZ = BIT(2), + + /** 22.05 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_22KHZ = BIT(3), + + /** 24 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_24KHZ = BIT(4), + + /** 32 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_32KHZ = BIT(5), + + /** 44.1 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_44KHZ = BIT(6), + + /** 48 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_48KHZ = BIT(7), + + /** 88.2 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_88KHZ = BIT(8), + + /** 96 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_96KHZ = BIT(9), + + /** 176.4 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_176KHZ = BIT(10), + + /** 192 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_192KHZ = BIT(11), + + /** 384 Khz sampling frequency */ + BT_AUDIO_CODEC_CAP_FREQ_384KHZ = BIT(12), + + /** Any frequency capability */ + BT_AUDIO_CODEC_CAP_FREQ_ANY = + (BT_AUDIO_CODEC_CAP_FREQ_8KHZ | BT_AUDIO_CODEC_CAP_FREQ_11KHZ | + BT_AUDIO_CODEC_CAP_FREQ_16KHZ | BT_AUDIO_CODEC_CAP_FREQ_22KHZ | + BT_AUDIO_CODEC_CAP_FREQ_24KHZ | BT_AUDIO_CODEC_CAP_FREQ_32KHZ | + BT_AUDIO_CODEC_CAP_FREQ_44KHZ | BT_AUDIO_CODEC_CAP_FREQ_48KHZ | + BT_AUDIO_CODEC_CAP_FREQ_88KHZ | BT_AUDIO_CODEC_CAP_FREQ_96KHZ | + BT_AUDIO_CODEC_CAP_FREQ_176KHZ | BT_AUDIO_CODEC_CAP_FREQ_192KHZ | + BT_AUDIO_CODEC_CAP_FREQ_384KHZ), +}; + +/** @brief Supported frame durations bitfield */ +enum bt_audio_codec_cap_frame_dur { + /** 7.5 msec frame duration capability */ + BT_AUDIO_CODEC_CAP_DURATION_7_5 = BIT(0), + + /** 10 msec frame duration capability */ + BT_AUDIO_CODEC_CAP_DURATION_10 = BIT(1), + + /** Any frame duration capability */ + BT_AUDIO_CODEC_CAP_DURATION_ANY = + (BT_AUDIO_CODEC_CAP_DURATION_7_5 | BT_AUDIO_CODEC_CAP_DURATION_10), + + /** + * @brief 7.5 msec preferred frame duration capability. + * + * This shall only be set if @ref BT_AUDIO_CODEC_CAP_DURATION_7_5 is also set, and if @ref + * BT_AUDIO_CODEC_CAP_DURATION_PREFER_10 is not set. + */ + BT_AUDIO_CODEC_CAP_DURATION_PREFER_7_5 = BIT(4), + + /** + * @brief 10 msec preferred frame duration capability + * + * This shall only be set if @ref BT_AUDIO_CODEC_CAP_DURATION_10 is also set, and if @ref + * BT_AUDIO_CODEC_CAP_DURATION_PREFER_7_5 is not set. + */ + BT_AUDIO_CODEC_CAP_DURATION_PREFER_10 = BIT(5), +}; + +/** Supported audio capabilities channel count bitfield */ +enum bt_audio_codec_cap_chan_count { + /** Supporting 1 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_1 = BIT(0), + + /** Supporting 2 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_2 = BIT(1), + + /** Supporting 3 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_3 = BIT(2), + + /** Supporting 4 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_4 = BIT(3), + + /** Supporting 5 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_5 = BIT(4), + + /** Supporting 6 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_6 = BIT(5), + + /** Supporting 7 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_7 = BIT(6), + + /** Supporting 8 channel */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_8 = BIT(7), + + /** Supporting all channels */ + BT_AUDIO_CODEC_CAP_CHAN_COUNT_ANY = + (BT_AUDIO_CODEC_CAP_CHAN_COUNT_1 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_2 | + BT_AUDIO_CODEC_CAP_CHAN_COUNT_3 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_4 | + BT_AUDIO_CODEC_CAP_CHAN_COUNT_5 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_6 | + BT_AUDIO_CODEC_CAP_CHAN_COUNT_7 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_8), +}; + +/** Minimum supported channel counts */ +#define BT_AUDIO_CODEC_CAP_CHAN_COUNT_MIN 1 +/** Maximum supported channel counts */ +#define BT_AUDIO_CODEC_CAP_CHAN_COUNT_MAX 8 + +/** The minimum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */ +#define BT_AUDIO_BROADCAST_NAME_LEN_MIN 4 +/** The maximum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */ +#define BT_AUDIO_BROADCAST_NAME_LEN_MAX 128 + +/** + * @brief Codec configuration types + * + * Used to build and parse codec configurations as specified in the ASCS and BAP specifications. + * Source is assigned numbers for Generic Audio, bluetooth.com. + */ +enum bt_audio_codec_cfg_type { + /** Sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ = 0x01, + + /** Frame duration */ + BT_AUDIO_CODEC_CFG_DURATION = 0x02, + + /** Audio channel allocation */ + BT_AUDIO_CODEC_CFG_CHAN_ALLOC = 0x03, + + /** Octets per codec frame */ + BT_AUDIO_CODEC_CFG_FRAME_LEN = 0x04, + + /** Codec frame blocks per SDU */ + BT_AUDIO_CODEC_CFG_FRAME_BLKS_PER_SDU = 0x05, +}; + +/** Codec configuration sampling freqency */ +enum bt_audio_codec_cfg_freq { + /** 8 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_8KHZ = 0x01, + + /** 11.025 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_11KHZ = 0x02, + + /** 16 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_16KHZ = 0x03, + + /** 22.05 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_22KHZ = 0x04, + + /** 24 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_24KHZ = 0x05, + + /** 32 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_32KHZ = 0x06, + + /** 44.1 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_44KHZ = 0x07, + + /** 48 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_48KHZ = 0x08, + + /** 88.2 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_88KHZ = 0x09, + + /** 96 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_96KHZ = 0x0a, + + /** 176.4 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_176KHZ = 0x0b, + + /** 192 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_192KHZ = 0x0c, + + /** 384 Khz codec sampling frequency */ + BT_AUDIO_CODEC_CFG_FREQ_384KHZ = 0x0d, +}; + +/** Codec configuration frame duration */ +enum bt_audio_codec_cfg_frame_dur { + /** 7.5 msec Frame Duration configuration */ + BT_AUDIO_CODEC_CFG_DURATION_7_5 = 0x00, + + /** 10 msec Frame Duration configuration */ + BT_AUDIO_CODEC_CFG_DURATION_10 = 0x01, +}; + +/** + * @brief Audio Context Type for Generic Audio + * + * These values are defined by the Generic Audio Assigned Numbers, bluetooth.com + */ +enum bt_audio_context { + /** No context type */ + BT_AUDIO_CONTEXT_TYPE_NONE = 0, + /** + * Identifies audio where the use case context does not match any other defined value, + * or where the context is unknown or cannot be determined. + */ + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED = BIT(0), + /** + * Conversation between humans, for example, in telephony or video calls, including + * traditional cellular as well as VoIP and Push-to-Talk + */ + BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL = BIT(1), + /** Media, for example, music playback, radio, podcast or movie soundtrack, or tv audio */ + BT_AUDIO_CONTEXT_TYPE_MEDIA = BIT(2), + /** + * Audio associated with video gaming, for example gaming media; gaming effects; music + * and in-game voice chat between participants; or a mix of all the above + */ + BT_AUDIO_CONTEXT_TYPE_GAME = BIT(3), + /** Instructional audio, for example, in navigation, announcements, or user guidance */ + BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL = BIT(4), + /** Man-machine communication, for example, with voice recognition or virtual assistants */ + BT_AUDIO_CONTEXT_TYPE_VOICE_ASSISTANTS = BIT(5), + /** + * Live audio, for example, from a microphone where audio is perceived both through a + * direct acoustic path and through an LE Audio Stream + */ + BT_AUDIO_CONTEXT_TYPE_LIVE = BIT(6), + /** + * Sound effects including keyboard and touch feedback; menu and user interface sounds; + * and other system sounds + */ + BT_AUDIO_CONTEXT_TYPE_SOUND_EFFECTS = BIT(7), + /** + * Notification and reminder sounds; attention-seeking audio, for example, + * in beeps signaling the arrival of a message + */ + BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS = BIT(8), + /** + * Alerts the user to an incoming call, for example, an incoming telephony or video call, + * including traditional cellular as well as VoIP and Push-to-Talk + */ + BT_AUDIO_CONTEXT_TYPE_RINGTONE = BIT(9), + /** + * Alarms and timers; immediate alerts, for example, in a critical battery alarm, + * timer expiry or alarm clock, toaster, cooker, kettle, microwave, etc. + */ + BT_AUDIO_CONTEXT_TYPE_ALERTS = BIT(10), + /** Emergency alarm Emergency sounds, for example, fire alarms or other urgent alerts */ + BT_AUDIO_CONTEXT_TYPE_EMERGENCY_ALARM = BIT(11), +}; + +/** + * Any known context. + */ +#define BT_AUDIO_CONTEXT_TYPE_ANY (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \ + BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ + BT_AUDIO_CONTEXT_TYPE_MEDIA | \ + BT_AUDIO_CONTEXT_TYPE_GAME | \ + BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL | \ + BT_AUDIO_CONTEXT_TYPE_VOICE_ASSISTANTS | \ + BT_AUDIO_CONTEXT_TYPE_LIVE | \ + BT_AUDIO_CONTEXT_TYPE_SOUND_EFFECTS | \ + BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS | \ + BT_AUDIO_CONTEXT_TYPE_RINGTONE | \ + BT_AUDIO_CONTEXT_TYPE_ALERTS | \ + BT_AUDIO_CONTEXT_TYPE_EMERGENCY_ALARM) + +/** + * @brief Parental rating defined by the Generic Audio assigned numbers (bluetooth.com). + * + * The numbering scheme is aligned with Annex F of EN 300 707 v1.2.1 which + * defined parental rating for viewing. + */ +enum bt_audio_parental_rating { + /** No rating */ + BT_AUDIO_PARENTAL_RATING_NO_RATING = 0x00, + /** For all ages */ + BT_AUDIO_PARENTAL_RATING_AGE_ANY = 0x01, + /** Recommended for listeners of age 5 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_5_OR_ABOVE = 0x02, + /** Recommended for listeners of age 6 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_6_OR_ABOVE = 0x03, + /** Recommended for listeners of age 7 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_7_OR_ABOVE = 0x04, + /** Recommended for listeners of age 8 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_8_OR_ABOVE = 0x05, + /** Recommended for listeners of age 9 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_9_OR_ABOVE = 0x06, + /** Recommended for listeners of age 10 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_10_OR_ABOVE = 0x07, + /** Recommended for listeners of age 11 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_11_OR_ABOVE = 0x08, + /** Recommended for listeners of age 12 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_12_OR_ABOVE = 0x09, + /** Recommended for listeners of age 13 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_13_OR_ABOVE = 0x0A, + /** Recommended for listeners of age 14 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_14_OR_ABOVE = 0x0B, + /** Recommended for listeners of age 15 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_15_OR_ABOVE = 0x0C, + /** Recommended for listeners of age 16 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_16_OR_ABOVE = 0x0D, + /** Recommended for listeners of age 17 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_17_OR_ABOVE = 0x0E, + /** Recommended for listeners of age 18 and above */ + BT_AUDIO_PARENTAL_RATING_AGE_18_OR_ABOVE = 0x0F +}; + +/** @brief Audio Active State defined by the Generic Audio assigned numbers (bluetooth.com). */ +enum bt_audio_active_state { + /** No audio data is being transmitted */ + BT_AUDIO_ACTIVE_STATE_DISABLED = 0x00, + /** Audio data is being transmitted */ + BT_AUDIO_ACTIVE_STATE_ENABLED = 0x01, +}; + +/** Assisted Listening Stream defined by the Generic Audio assigned numbers (bluetooth.com). */ +enum bt_audio_assisted_listening_stream { + /** Unspecified audio enhancement */ + BT_AUDIO_ASSISTED_LISTENING_STREAM_UNSPECIFIED = 0x00, +}; + +/** + * @brief Codec metadata type IDs + * + * Metadata types defined by the Generic Audio assigned numbers (bluetooth.com). + */ +enum bt_audio_metadata_type { + /** + * @brief Preferred audio context. + * + * Bitfield of preferred audio contexts. + * + * If 0, the context type is not a preferred use case for this codec + * configuration. + * + * See the BT_AUDIO_CONTEXT_* for valid values. + */ + BT_AUDIO_METADATA_TYPE_PREF_CONTEXT = 0x01, + + /** + * @brief Streaming audio context. + * + * Bitfield of streaming audio contexts. + * + * If 0, the context type is not a preferred use case for this codec + * configuration. + * + * See the BT_AUDIO_CONTEXT_* for valid values. + */ + BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT = 0x02, + + /** UTF-8 encoded title or summary of stream content */ + BT_AUDIO_METADATA_TYPE_PROGRAM_INFO = 0x03, + + /** + * @brief Language + * + * 3 octet lower case language code defined by ISO 639-3 + * Possible values can be found at https://iso639-3.sil.org/code_tables/639/data + */ + BT_AUDIO_METADATA_TYPE_LANG = 0x04, + + /** Array of 8-bit CCID values */ + BT_AUDIO_METADATA_TYPE_CCID_LIST = 0x05, + + /** + * @brief Parental rating + * + * See @ref bt_audio_parental_rating for valid values. + */ + BT_AUDIO_METADATA_TYPE_PARENTAL_RATING = 0x06, + + /** UTF-8 encoded URI for additional Program information */ + BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI = 0x07, + + /** + * @brief Audio active state + * + * See @ref bt_audio_active_state for valid values. + */ + BT_AUDIO_METADATA_TYPE_AUDIO_STATE = 0x08, + + /** Broadcast Audio Immediate Rendering flag */ + BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE = 0x09, + + /** + * @brief Assisted listening stream + * + * See @ref bt_audio_assisted_listening_stream for valid values. + */ + BT_AUDIO_METADATA_TYPE_ASSISTED_LISTENING_STREAM = 0x0A, + + /** UTF-8 encoded Broadcast name */ + BT_AUDIO_METADATA_TYPE_BROADCAST_NAME = 0x0B, + + /** Extended metadata */ + BT_AUDIO_METADATA_TYPE_EXTENDED = 0xFE, + + /** Vendor specific metadata */ + BT_AUDIO_METADATA_TYPE_VENDOR = 0xFF, +}; + +/** + * @brief Location values for BT Audio. + * + * These values are defined by the Generic Audio Assigned Numbers, bluetooth.com + */ +enum bt_audio_location { + /** Mono Audio (no specified Audio Location) */ + BT_AUDIO_LOCATION_MONO_AUDIO = 0, + /** Front Left */ + BT_AUDIO_LOCATION_FRONT_LEFT = BIT(0), + /** Front Right */ + BT_AUDIO_LOCATION_FRONT_RIGHT = BIT(1), + /** Front Center */ + BT_AUDIO_LOCATION_FRONT_CENTER = BIT(2), + /** Low Frequency Effects 1 */ + BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_1 = BIT(3), + /** Back Left */ + BT_AUDIO_LOCATION_BACK_LEFT = BIT(4), + /** Back Right */ + BT_AUDIO_LOCATION_BACK_RIGHT = BIT(5), + /** Front Left of Center */ + BT_AUDIO_LOCATION_FRONT_LEFT_OF_CENTER = BIT(6), + /** Front Right of Center */ + BT_AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER = BIT(7), + /** Back Center */ + BT_AUDIO_LOCATION_BACK_CENTER = BIT(8), + /** Low Frequency Effects 2 */ + BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_2 = BIT(9), + /** Side Left */ + BT_AUDIO_LOCATION_SIDE_LEFT = BIT(10), + /** Side Right */ + BT_AUDIO_LOCATION_SIDE_RIGHT = BIT(11), + /** Top Front Left */ + BT_AUDIO_LOCATION_TOP_FRONT_LEFT = BIT(12), + /** Top Front Right */ + BT_AUDIO_LOCATION_TOP_FRONT_RIGHT = BIT(13), + /** Top Front Center */ + BT_AUDIO_LOCATION_TOP_FRONT_CENTER = BIT(14), + /** Top Center */ + BT_AUDIO_LOCATION_TOP_CENTER = BIT(15), + /** Top Back Left */ + BT_AUDIO_LOCATION_TOP_BACK_LEFT = BIT(16), + /** Top Back Right */ + BT_AUDIO_LOCATION_TOP_BACK_RIGHT = BIT(17), + /** Top Side Left */ + BT_AUDIO_LOCATION_TOP_SIDE_LEFT = BIT(18), + /** Top Side Right */ + BT_AUDIO_LOCATION_TOP_SIDE_RIGHT = BIT(19), + /** Top Back Center */ + BT_AUDIO_LOCATION_TOP_BACK_CENTER = BIT(20), + /** Bottom Front Center */ + BT_AUDIO_LOCATION_BOTTOM_FRONT_CENTER = BIT(21), + /** Bottom Front Left */ + BT_AUDIO_LOCATION_BOTTOM_FRONT_LEFT = BIT(22), + /** Bottom Front Right */ + BT_AUDIO_LOCATION_BOTTOM_FRONT_RIGHT = BIT(23), + /** Front Left Wide */ + BT_AUDIO_LOCATION_FRONT_LEFT_WIDE = BIT(24), + /** Front Right Wide */ + BT_AUDIO_LOCATION_FRONT_RIGHT_WIDE = BIT(25), + /** Left Surround */ + BT_AUDIO_LOCATION_LEFT_SURROUND = BIT(26), + /** Right Surround */ + BT_AUDIO_LOCATION_RIGHT_SURROUND = BIT(27), +}; + +/** + * Any known location. + */ +#define BT_AUDIO_LOCATION_ANY (BT_AUDIO_LOCATION_FRONT_LEFT | \ + BT_AUDIO_LOCATION_FRONT_RIGHT | \ + BT_AUDIO_LOCATION_FRONT_CENTER | \ + BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_1 | \ + BT_AUDIO_LOCATION_BACK_LEFT | \ + BT_AUDIO_LOCATION_BACK_RIGHT | \ + BT_AUDIO_LOCATION_FRONT_LEFT_OF_CENTER | \ + BT_AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER | \ + BT_AUDIO_LOCATION_BACK_CENTER | \ + BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_2 | \ + BT_AUDIO_LOCATION_SIDE_LEFT | \ + BT_AUDIO_LOCATION_SIDE_RIGHT | \ + BT_AUDIO_LOCATION_TOP_FRONT_LEFT | \ + BT_AUDIO_LOCATION_TOP_FRONT_RIGHT | \ + BT_AUDIO_LOCATION_TOP_FRONT_CENTER | \ + BT_AUDIO_LOCATION_TOP_CENTER | \ + BT_AUDIO_LOCATION_TOP_BACK_LEFT | \ + BT_AUDIO_LOCATION_TOP_BACK_RIGHT | \ + BT_AUDIO_LOCATION_TOP_SIDE_LEFT | \ + BT_AUDIO_LOCATION_TOP_SIDE_RIGHT | \ + BT_AUDIO_LOCATION_TOP_BACK_CENTER | \ + BT_AUDIO_LOCATION_BOTTOM_FRONT_CENTER | \ + BT_AUDIO_LOCATION_BOTTOM_FRONT_LEFT | \ + BT_AUDIO_LOCATION_BOTTOM_FRONT_RIGHT | \ + BT_AUDIO_LOCATION_FRONT_LEFT_WIDE | \ + BT_AUDIO_LOCATION_FRONT_RIGHT_WIDE | \ + BT_AUDIO_LOCATION_LEFT_SURROUND | \ + BT_AUDIO_LOCATION_RIGHT_SURROUND) + +/** @} */ /* end of bt_assigned_numbers_audio */ + +/** + * @name Company Identifiers (see Bluetooth Assigned Numbers) + * @{ + */ + +#define BT_COMP_ID_LF 0x05f1 /**< The Linux Foundation */ + +/** @} */ /* end of @name Company Identifiers */ + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_ASSIGNED_NUMBERS_H_ */ diff --git a/include/zephyr/bluetooth/audio/audio.h b/include/zephyr/bluetooth/audio/audio.h index 230f2735e4d5..87eac9d4a203 100644 --- a/include/zephyr/bluetooth/audio/audio.h +++ b/include/zephyr/bluetooth/audio/audio.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -49,157 +50,10 @@ extern "C" { #define BT_AUDIO_PD_MAX 0xFFFFFFU /** Indicates that the unicast server does not have a preference for any retransmission number */ #define BT_AUDIO_RTN_PREF_NONE 0xFFU -/** The minimum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */ -#define BT_AUDIO_BROADCAST_NAME_LEN_MIN 4 -/** The maximum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */ -#define BT_AUDIO_BROADCAST_NAME_LEN_MAX 128 /** Size of the stream language value, e.g. "eng" */ #define BT_AUDIO_LANG_SIZE 3 -/** - * @brief Codec capability types - * - * Used to build and parse codec capabilities as specified in the PAC specification. - * Source is assigned numbers for Generic Audio, bluetooth.com. - */ -enum bt_audio_codec_cap_type { - /** Supported sampling frequencies */ - BT_AUDIO_CODEC_CAP_TYPE_FREQ = 0x01, - - /** Supported frame durations */ - BT_AUDIO_CODEC_CAP_TYPE_DURATION = 0x02, - - /** Supported audio channel counts */ - BT_AUDIO_CODEC_CAP_TYPE_CHAN_COUNT = 0x03, - - /** Supported octets per codec frame */ - BT_AUDIO_CODEC_CAP_TYPE_FRAME_LEN = 0x04, - - /** Supported maximum codec frames per SDU */ - BT_AUDIO_CODEC_CAP_TYPE_FRAME_COUNT = 0x05, -}; - -/** @brief Supported frequencies bitfield */ -enum bt_audio_codec_cap_freq { - /** 8 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_8KHZ = BIT(0), - - /** 11.025 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_11KHZ = BIT(1), - - /** 16 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_16KHZ = BIT(2), - - /** 22.05 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_22KHZ = BIT(3), - - /** 24 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_24KHZ = BIT(4), - - /** 32 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_32KHZ = BIT(5), - - /** 44.1 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_44KHZ = BIT(6), - - /** 48 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_48KHZ = BIT(7), - - /** 88.2 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_88KHZ = BIT(8), - - /** 96 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_96KHZ = BIT(9), - - /** 176.4 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_176KHZ = BIT(10), - - /** 192 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_192KHZ = BIT(11), - - /** 384 Khz sampling frequency */ - BT_AUDIO_CODEC_CAP_FREQ_384KHZ = BIT(12), - - /** Any frequency capability */ - BT_AUDIO_CODEC_CAP_FREQ_ANY = - (BT_AUDIO_CODEC_CAP_FREQ_8KHZ | BT_AUDIO_CODEC_CAP_FREQ_11KHZ | - BT_AUDIO_CODEC_CAP_FREQ_16KHZ | BT_AUDIO_CODEC_CAP_FREQ_22KHZ | - BT_AUDIO_CODEC_CAP_FREQ_24KHZ | BT_AUDIO_CODEC_CAP_FREQ_32KHZ | - BT_AUDIO_CODEC_CAP_FREQ_44KHZ | BT_AUDIO_CODEC_CAP_FREQ_48KHZ | - BT_AUDIO_CODEC_CAP_FREQ_88KHZ | BT_AUDIO_CODEC_CAP_FREQ_96KHZ | - BT_AUDIO_CODEC_CAP_FREQ_176KHZ | BT_AUDIO_CODEC_CAP_FREQ_192KHZ | - BT_AUDIO_CODEC_CAP_FREQ_384KHZ), -}; - -/** @brief Supported frame durations bitfield */ -enum bt_audio_codec_cap_frame_dur { - /** 7.5 msec frame duration capability */ - BT_AUDIO_CODEC_CAP_DURATION_7_5 = BIT(0), - - /** 10 msec frame duration capability */ - BT_AUDIO_CODEC_CAP_DURATION_10 = BIT(1), - - /** Any frame duration capability */ - BT_AUDIO_CODEC_CAP_DURATION_ANY = - (BT_AUDIO_CODEC_CAP_DURATION_7_5 | BT_AUDIO_CODEC_CAP_DURATION_10), - - /** - * @brief 7.5 msec preferred frame duration capability. - * - * This shall only be set if @ref BT_AUDIO_CODEC_CAP_DURATION_7_5 is also set, and if @ref - * BT_AUDIO_CODEC_CAP_DURATION_PREFER_10 is not set. - */ - BT_AUDIO_CODEC_CAP_DURATION_PREFER_7_5 = BIT(4), - - /** - * @brief 10 msec preferred frame duration capability - * - * This shall only be set if @ref BT_AUDIO_CODEC_CAP_DURATION_10 is also set, and if @ref - * BT_AUDIO_CODEC_CAP_DURATION_PREFER_7_5 is not set. - */ - BT_AUDIO_CODEC_CAP_DURATION_PREFER_10 = BIT(5), -}; - -/** Supported audio capabilities channel count bitfield */ -enum bt_audio_codec_cap_chan_count { - /** Supporting 1 channel */ - BT_AUDIO_CODEC_CAP_CHAN_COUNT_1 = BIT(0), - - /** Supporting 2 channel */ - BT_AUDIO_CODEC_CAP_CHAN_COUNT_2 = BIT(1), - - /** Supporting 3 channel */ - BT_AUDIO_CODEC_CAP_CHAN_COUNT_3 = BIT(2), - - /** Supporting 4 channel */ - BT_AUDIO_CODEC_CAP_CHAN_COUNT_4 = BIT(3), - - /** Supporting 5 channel */ - BT_AUDIO_CODEC_CAP_CHAN_COUNT_5 = BIT(4), - - /** Supporting 6 channel */ - BT_AUDIO_CODEC_CAP_CHAN_COUNT_6 = BIT(5), - - /** Supporting 7 channel */ - BT_AUDIO_CODEC_CAP_CHAN_COUNT_7 = BIT(6), - - /** Supporting 8 channel */ - BT_AUDIO_CODEC_CAP_CHAN_COUNT_8 = BIT(7), - - /** Supporting all channels */ - BT_AUDIO_CODEC_CAP_CHAN_COUNT_ANY = - (BT_AUDIO_CODEC_CAP_CHAN_COUNT_1 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_2 | - BT_AUDIO_CODEC_CAP_CHAN_COUNT_3 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_4 | - BT_AUDIO_CODEC_CAP_CHAN_COUNT_5 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_6 | - BT_AUDIO_CODEC_CAP_CHAN_COUNT_7 | BT_AUDIO_CODEC_CAP_CHAN_COUNT_8), -}; - -/** Minimum supported channel counts */ -#define BT_AUDIO_CODEC_CAP_CHAN_COUNT_MIN 1 -/** Maximum supported channel counts */ -#define BT_AUDIO_CODEC_CAP_CHAN_COUNT_MAX 8 - /** * @brief Channel count support capability * @@ -221,290 +75,6 @@ struct bt_audio_codec_octets_per_codec_frame { uint16_t max; }; -/** - * @brief Codec configuration types - * - * Used to build and parse codec configurations as specified in the ASCS and BAP specifications. - * Source is assigned numbers for Generic Audio, bluetooth.com. - */ -enum bt_audio_codec_cfg_type { - /** Sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ = 0x01, - - /** Frame duration */ - BT_AUDIO_CODEC_CFG_DURATION = 0x02, - - /** Audio channel allocation */ - BT_AUDIO_CODEC_CFG_CHAN_ALLOC = 0x03, - - /** Octets per codec frame */ - BT_AUDIO_CODEC_CFG_FRAME_LEN = 0x04, - - /** Codec frame blocks per SDU */ - BT_AUDIO_CODEC_CFG_FRAME_BLKS_PER_SDU = 0x05, -}; - -/** Codec configuration sampling freqency */ -enum bt_audio_codec_cfg_freq { - /** 8 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_8KHZ = 0x01, - - /** 11.025 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_11KHZ = 0x02, - - /** 16 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_16KHZ = 0x03, - - /** 22.05 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_22KHZ = 0x04, - - /** 24 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_24KHZ = 0x05, - - /** 32 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_32KHZ = 0x06, - - /** 44.1 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_44KHZ = 0x07, - - /** 48 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_48KHZ = 0x08, - - /** 88.2 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_88KHZ = 0x09, - - /** 96 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_96KHZ = 0x0a, - - /** 176.4 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_176KHZ = 0x0b, - - /** 192 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_192KHZ = 0x0c, - - /** 384 Khz codec sampling frequency */ - BT_AUDIO_CODEC_CFG_FREQ_384KHZ = 0x0d, -}; - -/** Codec configuration frame duration */ -enum bt_audio_codec_cfg_frame_dur { - /** 7.5 msec Frame Duration configuration */ - BT_AUDIO_CODEC_CFG_DURATION_7_5 = 0x00, - - /** 10 msec Frame Duration configuration */ - BT_AUDIO_CODEC_CFG_DURATION_10 = 0x01, -}; - -/** - * @brief Audio Context Type for Generic Audio - * - * These values are defined by the Generic Audio Assigned Numbers, bluetooth.com - */ -enum bt_audio_context { - /** No context type */ - BT_AUDIO_CONTEXT_TYPE_NONE = 0, - /** - * Identifies audio where the use case context does not match any other defined value, - * or where the context is unknown or cannot be determined. - */ - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED = BIT(0), - /** - * Conversation between humans, for example, in telephony or video calls, including - * traditional cellular as well as VoIP and Push-to-Talk - */ - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL = BIT(1), - /** Media, for example, music playback, radio, podcast or movie soundtrack, or tv audio */ - BT_AUDIO_CONTEXT_TYPE_MEDIA = BIT(2), - /** - * Audio associated with video gaming, for example gaming media; gaming effects; music - * and in-game voice chat between participants; or a mix of all the above - */ - BT_AUDIO_CONTEXT_TYPE_GAME = BIT(3), - /** Instructional audio, for example, in navigation, announcements, or user guidance */ - BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL = BIT(4), - /** Man-machine communication, for example, with voice recognition or virtual assistants */ - BT_AUDIO_CONTEXT_TYPE_VOICE_ASSISTANTS = BIT(5), - /** - * Live audio, for example, from a microphone where audio is perceived both through a - * direct acoustic path and through an LE Audio Stream - */ - BT_AUDIO_CONTEXT_TYPE_LIVE = BIT(6), - /** - * Sound effects including keyboard and touch feedback; menu and user interface sounds; - * and other system sounds - */ - BT_AUDIO_CONTEXT_TYPE_SOUND_EFFECTS = BIT(7), - /** - * Notification and reminder sounds; attention-seeking audio, for example, - * in beeps signaling the arrival of a message - */ - BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS = BIT(8), - /** - * Alerts the user to an incoming call, for example, an incoming telephony or video call, - * including traditional cellular as well as VoIP and Push-to-Talk - */ - BT_AUDIO_CONTEXT_TYPE_RINGTONE = BIT(9), - /** - * Alarms and timers; immediate alerts, for example, in a critical battery alarm, - * timer expiry or alarm clock, toaster, cooker, kettle, microwave, etc. - */ - BT_AUDIO_CONTEXT_TYPE_ALERTS = BIT(10), - /** Emergency alarm Emergency sounds, for example, fire alarms or other urgent alerts */ - BT_AUDIO_CONTEXT_TYPE_EMERGENCY_ALARM = BIT(11), -}; - -/** - * Any known context. - */ -#define BT_AUDIO_CONTEXT_TYPE_ANY (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \ - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ - BT_AUDIO_CONTEXT_TYPE_MEDIA | \ - BT_AUDIO_CONTEXT_TYPE_GAME | \ - BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL | \ - BT_AUDIO_CONTEXT_TYPE_VOICE_ASSISTANTS | \ - BT_AUDIO_CONTEXT_TYPE_LIVE | \ - BT_AUDIO_CONTEXT_TYPE_SOUND_EFFECTS | \ - BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS | \ - BT_AUDIO_CONTEXT_TYPE_RINGTONE | \ - BT_AUDIO_CONTEXT_TYPE_ALERTS | \ - BT_AUDIO_CONTEXT_TYPE_EMERGENCY_ALARM) - -/** - * @brief Parental rating defined by the Generic Audio assigned numbers (bluetooth.com). - * - * The numbering scheme is aligned with Annex F of EN 300 707 v1.2.1 which - * defined parental rating for viewing. - */ -enum bt_audio_parental_rating { - /** No rating */ - BT_AUDIO_PARENTAL_RATING_NO_RATING = 0x00, - /** For all ages */ - BT_AUDIO_PARENTAL_RATING_AGE_ANY = 0x01, - /** Recommended for listeners of age 5 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_5_OR_ABOVE = 0x02, - /** Recommended for listeners of age 6 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_6_OR_ABOVE = 0x03, - /** Recommended for listeners of age 7 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_7_OR_ABOVE = 0x04, - /** Recommended for listeners of age 8 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_8_OR_ABOVE = 0x05, - /** Recommended for listeners of age 9 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_9_OR_ABOVE = 0x06, - /** Recommended for listeners of age 10 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_10_OR_ABOVE = 0x07, - /** Recommended for listeners of age 11 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_11_OR_ABOVE = 0x08, - /** Recommended for listeners of age 12 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_12_OR_ABOVE = 0x09, - /** Recommended for listeners of age 13 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_13_OR_ABOVE = 0x0A, - /** Recommended for listeners of age 14 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_14_OR_ABOVE = 0x0B, - /** Recommended for listeners of age 15 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_15_OR_ABOVE = 0x0C, - /** Recommended for listeners of age 16 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_16_OR_ABOVE = 0x0D, - /** Recommended for listeners of age 17 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_17_OR_ABOVE = 0x0E, - /** Recommended for listeners of age 18 and above */ - BT_AUDIO_PARENTAL_RATING_AGE_18_OR_ABOVE = 0x0F -}; - -/** @brief Audio Active State defined by the Generic Audio assigned numbers (bluetooth.com). */ -enum bt_audio_active_state { - /** No audio data is being transmitted */ - BT_AUDIO_ACTIVE_STATE_DISABLED = 0x00, - /** Audio data is being transmitted */ - BT_AUDIO_ACTIVE_STATE_ENABLED = 0x01, -}; - -/** Assisted Listening Stream defined by the Generic Audio assigned numbers (bluetooth.com). */ -enum bt_audio_assisted_listening_stream { - /** Unspecified audio enhancement */ - BT_AUDIO_ASSISTED_LISTENING_STREAM_UNSPECIFIED = 0x00, -}; - -/** - * @brief Codec metadata type IDs - * - * Metadata types defined by the Generic Audio assigned numbers (bluetooth.com). - */ -enum bt_audio_metadata_type { - /** - * @brief Preferred audio context. - * - * Bitfield of preferred audio contexts. - * - * If 0, the context type is not a preferred use case for this codec - * configuration. - * - * See the BT_AUDIO_CONTEXT_* for valid values. - */ - BT_AUDIO_METADATA_TYPE_PREF_CONTEXT = 0x01, - - /** - * @brief Streaming audio context. - * - * Bitfield of streaming audio contexts. - * - * If 0, the context type is not a preferred use case for this codec - * configuration. - * - * See the BT_AUDIO_CONTEXT_* for valid values. - */ - BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT = 0x02, - - /** UTF-8 encoded title or summary of stream content */ - BT_AUDIO_METADATA_TYPE_PROGRAM_INFO = 0x03, - - /** - * @brief Language - * - * 3 octet lower case language code defined by ISO 639-3 - * Possible values can be found at https://iso639-3.sil.org/code_tables/639/data - */ - BT_AUDIO_METADATA_TYPE_LANG = 0x04, - - /** Array of 8-bit CCID values */ - BT_AUDIO_METADATA_TYPE_CCID_LIST = 0x05, - - /** - * @brief Parental rating - * - * See @ref bt_audio_parental_rating for valid values. - */ - BT_AUDIO_METADATA_TYPE_PARENTAL_RATING = 0x06, - - /** UTF-8 encoded URI for additional Program information */ - BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI = 0x07, - - /** - * @brief Audio active state - * - * See @ref bt_audio_active_state for valid values. - */ - BT_AUDIO_METADATA_TYPE_AUDIO_STATE = 0x08, - - /** Broadcast Audio Immediate Rendering flag */ - BT_AUDIO_METADATA_TYPE_BROADCAST_IMMEDIATE = 0x09, - - /** - * @brief Assisted listening stream - * - * See @ref bt_audio_assisted_listening_stream for valid values. - */ - BT_AUDIO_METADATA_TYPE_ASSISTED_LISTENING_STREAM = 0x0A, - - /** UTF-8 encoded Broadcast name */ - BT_AUDIO_METADATA_TYPE_BROADCAST_NAME = 0x0B, - - /** Extended metadata */ - BT_AUDIO_METADATA_TYPE_EXTENDED = 0xFE, - - /** Vendor specific metadata */ - BT_AUDIO_METADATA_TYPE_VENDOR = 0xFF, -}; - /** * @brief Helper to check whether metadata type is known by the stack. * @@ -586,104 +156,6 @@ enum bt_audio_metadata_type { .meta = _meta, \ }) -/** - * @brief Location values for BT Audio. - * - * These values are defined by the Generic Audio Assigned Numbers, bluetooth.com - */ -enum bt_audio_location { - /** Mono Audio (no specified Audio Location) */ - BT_AUDIO_LOCATION_MONO_AUDIO = 0, - /** Front Left */ - BT_AUDIO_LOCATION_FRONT_LEFT = BIT(0), - /** Front Right */ - BT_AUDIO_LOCATION_FRONT_RIGHT = BIT(1), - /** Front Center */ - BT_AUDIO_LOCATION_FRONT_CENTER = BIT(2), - /** Low Frequency Effects 1 */ - BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_1 = BIT(3), - /** Back Left */ - BT_AUDIO_LOCATION_BACK_LEFT = BIT(4), - /** Back Right */ - BT_AUDIO_LOCATION_BACK_RIGHT = BIT(5), - /** Front Left of Center */ - BT_AUDIO_LOCATION_FRONT_LEFT_OF_CENTER = BIT(6), - /** Front Right of Center */ - BT_AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER = BIT(7), - /** Back Center */ - BT_AUDIO_LOCATION_BACK_CENTER = BIT(8), - /** Low Frequency Effects 2 */ - BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_2 = BIT(9), - /** Side Left */ - BT_AUDIO_LOCATION_SIDE_LEFT = BIT(10), - /** Side Right */ - BT_AUDIO_LOCATION_SIDE_RIGHT = BIT(11), - /** Top Front Left */ - BT_AUDIO_LOCATION_TOP_FRONT_LEFT = BIT(12), - /** Top Front Right */ - BT_AUDIO_LOCATION_TOP_FRONT_RIGHT = BIT(13), - /** Top Front Center */ - BT_AUDIO_LOCATION_TOP_FRONT_CENTER = BIT(14), - /** Top Center */ - BT_AUDIO_LOCATION_TOP_CENTER = BIT(15), - /** Top Back Left */ - BT_AUDIO_LOCATION_TOP_BACK_LEFT = BIT(16), - /** Top Back Right */ - BT_AUDIO_LOCATION_TOP_BACK_RIGHT = BIT(17), - /** Top Side Left */ - BT_AUDIO_LOCATION_TOP_SIDE_LEFT = BIT(18), - /** Top Side Right */ - BT_AUDIO_LOCATION_TOP_SIDE_RIGHT = BIT(19), - /** Top Back Center */ - BT_AUDIO_LOCATION_TOP_BACK_CENTER = BIT(20), - /** Bottom Front Center */ - BT_AUDIO_LOCATION_BOTTOM_FRONT_CENTER = BIT(21), - /** Bottom Front Left */ - BT_AUDIO_LOCATION_BOTTOM_FRONT_LEFT = BIT(22), - /** Bottom Front Right */ - BT_AUDIO_LOCATION_BOTTOM_FRONT_RIGHT = BIT(23), - /** Front Left Wide */ - BT_AUDIO_LOCATION_FRONT_LEFT_WIDE = BIT(24), - /** Front Right Wide */ - BT_AUDIO_LOCATION_FRONT_RIGHT_WIDE = BIT(25), - /** Left Surround */ - BT_AUDIO_LOCATION_LEFT_SURROUND = BIT(26), - /** Right Surround */ - BT_AUDIO_LOCATION_RIGHT_SURROUND = BIT(27), -}; - -/** - * Any known location. - */ -#define BT_AUDIO_LOCATION_ANY (BT_AUDIO_LOCATION_FRONT_LEFT | \ - BT_AUDIO_LOCATION_FRONT_RIGHT | \ - BT_AUDIO_LOCATION_FRONT_CENTER | \ - BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_1 | \ - BT_AUDIO_LOCATION_BACK_LEFT | \ - BT_AUDIO_LOCATION_BACK_RIGHT | \ - BT_AUDIO_LOCATION_FRONT_LEFT_OF_CENTER | \ - BT_AUDIO_LOCATION_FRONT_RIGHT_OF_CENTER | \ - BT_AUDIO_LOCATION_BACK_CENTER | \ - BT_AUDIO_LOCATION_LOW_FREQ_EFFECTS_2 | \ - BT_AUDIO_LOCATION_SIDE_LEFT | \ - BT_AUDIO_LOCATION_SIDE_RIGHT | \ - BT_AUDIO_LOCATION_TOP_FRONT_LEFT | \ - BT_AUDIO_LOCATION_TOP_FRONT_RIGHT | \ - BT_AUDIO_LOCATION_TOP_FRONT_CENTER | \ - BT_AUDIO_LOCATION_TOP_CENTER | \ - BT_AUDIO_LOCATION_TOP_BACK_LEFT | \ - BT_AUDIO_LOCATION_TOP_BACK_RIGHT | \ - BT_AUDIO_LOCATION_TOP_SIDE_LEFT | \ - BT_AUDIO_LOCATION_TOP_SIDE_RIGHT | \ - BT_AUDIO_LOCATION_TOP_BACK_CENTER | \ - BT_AUDIO_LOCATION_BOTTOM_FRONT_CENTER | \ - BT_AUDIO_LOCATION_BOTTOM_FRONT_LEFT | \ - BT_AUDIO_LOCATION_BOTTOM_FRONT_RIGHT | \ - BT_AUDIO_LOCATION_FRONT_LEFT_WIDE | \ - BT_AUDIO_LOCATION_FRONT_RIGHT_WIDE | \ - BT_AUDIO_LOCATION_LEFT_SURROUND | \ - BT_AUDIO_LOCATION_RIGHT_SURROUND) - /** @brief Codec capability structure. */ struct bt_audio_codec_cap { /** Data path ID diff --git a/include/zephyr/bluetooth/bluetooth.h b/include/zephyr/bluetooth/bluetooth.h index 1656f1f56844..0739733c9543 100644 --- a/include/zephyr/bluetooth/bluetooth.h +++ b/include/zephyr/bluetooth/bluetooth.h @@ -691,71 +691,13 @@ enum bt_le_adv_opt { /** Convenience value when no options are specified. */ BT_LE_ADV_OPT_NONE = 0, - /** - * @brief Advertise as connectable. - * - * @deprecated Use @ref BT_LE_ADV_OPT_CONN instead. - * - * Advertise as connectable. If not connectable then the type of - * advertising is determined by providing scan response data. - * The advertiser address is determined by the type of advertising - * and/or enabling privacy @kconfig{CONFIG_BT_PRIVACY}. - * - * Starting connectable advertising preallocates a connection - * object. If this fails, the API returns @c -ENOMEM. - * - * When an advertiser set results in a connection creation, the - * controller automatically disables that advertising set. - * - * If the advertising set was started with @ref bt_le_adv_start - * without @ref BT_LE_ADV_OPT_ONE_TIME, the host will attempt to - * resume the advertiser under some conditions. - */ - BT_LE_ADV_OPT_CONNECTABLE __deprecated = BIT(0), - - /** - * @internal - * - * Internal access to the deprecated value to maintain the - * implementation of the deprecated feature. - * - * At the end of the deprecation period, ABI will change so - * `BT_LE_ADV_OPT_CONN` is just `BIT(0)`, removing the need for this - * symbol. - */ - _BT_LE_ADV_OPT_CONNECTABLE = BIT(0), - - /** - * @brief Advertise one time. - * - * @deprecated Use @ref BT_LE_ADV_OPT_CONN instead. - * - * Don't try to resume connectable advertising after a connection. - * This option is only meaningful when used together with - * BT_LE_ADV_OPT_CONNECTABLE. If set the advertising will be stopped - * when @ref bt_le_adv_stop is called or when an incoming (peripheral) - * connection happens. If this option is not set the stack will - * take care of keeping advertising enabled even as connections - * occur. - * If Advertising directed or the advertiser was started with - * @ref bt_le_ext_adv_start then this behavior is the default behavior - * and this flag has no effect. - */ - BT_LE_ADV_OPT_ONE_TIME __deprecated = BIT(1), - - /** - * @internal - * - * Internal access to the deprecated value to maintain - * the implementation of the deprecated feature. - */ - _BT_LE_ADV_OPT_ONE_TIME = BIT(1), - /** * @brief Connectable advertising * * Starting connectable advertising preallocates a connection * object. If this fails, the API returns @c -ENOMEM. + * Stopping connectable advertising will free the connection object, + * and will trigger a call to @ref bt_conn_cb.recycled. * * The advertising set stops immediately after it creates a * connection. This happens automatically in the controller. @@ -1163,17 +1105,6 @@ struct bt_le_per_adv_param { #define BT_LE_ADV_CONN_DIR(_peer) BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONN, 0, 0, _peer) -/** - * @deprecated This is a convenience macro for @ref - * BT_LE_ADV_OPT_CONNECTABLE, which is deprecated. Please use - * @ref BT_LE_ADV_CONN_FAST_1 or @ref BT_LE_ADV_CONN_FAST_2 - * instead. - */ -#define BT_LE_ADV_CONN \ - BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, BT_GAP_ADV_FAST_INT_MIN_2, \ - BT_GAP_ADV_FAST_INT_MAX_2, NULL) \ - __DEPRECATED_MACRO - /** * @brief GAP recommended connectable advertising parameters user-initiated * @@ -1218,10 +1149,6 @@ struct bt_le_per_adv_param { * - Limited Discoverable Mode * - General Discoverable Mode * - * The advertising interval corresponds to what was offered as @ref BT_LE_ADV_CONN in Zephyr 3.6 and - * earlier, but unlike @ref BT_LE_ADV_CONN, the host does not automatically resume the advertiser - * after it results in a connection. - * * See Bluetooth Core Specification: * - 6.0 Vol 3, Part C, Appendix A "Timers and Constants", T_GAP(adv_fast_interval2) * - 6.0 Vol 3, Part C, Section 9.3.11 "Connection Establishment Timing parameters" @@ -1230,8 +1157,6 @@ struct bt_le_per_adv_param { BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONN, BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, \ NULL) -#define BT_LE_ADV_CONN_ONE_TIME BT_LE_ADV_CONN_FAST_2 __DEPRECATED_MACRO - #define BT_LE_ADV_CONN_DIR_LOW_DUTY(_peer) \ BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONN | BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY, \ BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, _peer) @@ -1370,6 +1295,10 @@ struct bt_le_per_adv_param { * This error code is only guaranteed when using Zephyr * controller, for other controllers code returned in * this case may be -EIO. + * @return -EPERM When @kconfig{CONFIG_BT_PRIVACY} and + * @kconfig{CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS} are enabled and connectable + * advertising is requested, and the given local identity has a conflicting + * key with another local identity for which advertising is already started. */ int bt_le_adv_start(const struct bt_le_adv_param *param, const struct bt_data *ad, size_t ad_len, @@ -1497,6 +1426,12 @@ struct bt_le_ext_adv_start_param { * * @param adv Advertising set object. * @param param Advertise start parameters. + * + * @return Zero on success or (negative) error code otherwise. + * @return -EPERM When @kconfig{CONFIG_BT_PRIVACY} and + * @kconfig{CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS} are enabled and connectable + * advertising is requested, and the given local identity has a conflicting + * key with another local identity for which advertising is already started. */ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv, const struct bt_le_ext_adv_start_param *param); @@ -1667,7 +1602,7 @@ typedef void bt_le_scan_cb_t(const bt_addr_le_t *addr, int8_t rssi, * The periodic advertising parameters can only be set or updated on an * extended advertisement set which is neither scannable, connectable nor * anonymous (meaning, the advertising options @ref BT_LE_ADV_OPT_SCANNABLE, - * @ref BT_LE_ADV_OPT_CONNECTABLE and @ref BT_LE_ADV_OPT_ANONYMOUS cannot be set for @p adv). + * @ref BT_LE_ADV_OPT_CONN and @ref BT_LE_ADV_OPT_ANONYMOUS cannot be set for @p adv). * * @param adv Advertising set object. * @param param Advertising parameters. @@ -1683,7 +1618,7 @@ int bt_le_per_adv_set_param(struct bt_le_ext_adv *adv, * The periodic advertisement data can only be set or updated on an * extended advertisement set which is neither scannable, connectable nor * anonymous (meaning, the advertising options @ref BT_LE_ADV_OPT_SCANNABLE, - * @ref BT_LE_ADV_OPT_CONNECTABLE and @ref BT_LE_ADV_OPT_ANONYMOUS cannot be set for @p adv). + * @ref BT_LE_ADV_OPT_CONN and @ref BT_LE_ADV_OPT_ANONYMOUS cannot be set for @p adv). * * @param adv Advertising set object. * @param ad Advertising data. diff --git a/include/zephyr/bluetooth/buf.h b/include/zephyr/bluetooth/buf.h index a4b59dcbaa92..534c75559183 100644 --- a/include/zephyr/bluetooth/buf.h +++ b/include/zephyr/bluetooth/buf.h @@ -144,27 +144,20 @@ static inline enum bt_buf_type bt_buf_type_from_h4(uint8_t h4_type, enum bt_buf_ #define BT_BUF_ACL_RX_COUNT_MAX 65535 #if defined(CONFIG_BT_CONN) && defined(CONFIG_BT_HCI_HOST) - /* The host needs more ACL buffers than maximum ACL links. This is because of - * the way we re-assemble ACL packets into L2CAP PDUs. - * - * We keep around the first buffer (that comes from the driver) to do - * re-assembly into, and if all links are re-assembling, there will be no buffer - * available for the HCI driver to allocate from. - * - * TODO: When CONFIG_BT_BUF_ACL_RX_COUNT is removed, - * remove the MAX and only keep the 1. - */ +/* The host needs more ACL buffers than maximum ACL links. This is because of + * the way we re-assemble ACL packets into L2CAP PDUs. + * + * We keep around the first buffer (that comes from the driver) to do + * re-assembly into, and if all links are re-assembling, there will be no buffer + * available for the HCI driver to allocate from. + */ #define BT_BUF_ACL_RX_COUNT_EXTRA CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA -#define BT_BUF_ACL_RX_COUNT (MAX(CONFIG_BT_BUF_ACL_RX_COUNT, 1) + BT_BUF_ACL_RX_COUNT_EXTRA) +#define BT_BUF_ACL_RX_COUNT (1 + BT_BUF_ACL_RX_COUNT_EXTRA) #else #define BT_BUF_ACL_RX_COUNT_EXTRA 0 #define BT_BUF_ACL_RX_COUNT 0 #endif /* CONFIG_BT_CONN && CONFIG_BT_HCI_HOST */ -#if defined(CONFIG_BT_BUF_ACL_RX_COUNT) && CONFIG_BT_BUF_ACL_RX_COUNT > 0 -#warning "CONFIG_BT_BUF_ACL_RX_COUNT is deprecated, see Zephyr 4.1 migration guide" -#endif /* CONFIG_BT_BUF_ACL_RX_COUNT && CONFIG_BT_BUF_ACL_RX_COUNT > 0 */ - BUILD_ASSERT(BT_BUF_ACL_RX_COUNT <= BT_BUF_ACL_RX_COUNT_MAX, "Maximum number of ACL RX buffer is 65535, reduce CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA"); diff --git a/include/zephyr/bluetooth/conn.h b/include/zephyr/bluetooth/conn.h index 6a4b7c238c89..881d0894ee11 100644 --- a/include/zephyr/bluetooth/conn.h +++ b/include/zephyr/bluetooth/conn.h @@ -1639,23 +1639,6 @@ int bt_conn_le_create_auto(const struct bt_conn_le_create_param *create_param, */ int bt_conn_create_auto_stop(void); -/** @brief Automatically connect to remote device if it's in range. - * - * This function enables/disables automatic connection initiation. - * Every time the device loses the connection with peer, this connection - * will be re-established if connectable advertisement from peer is received. - * - * @note Auto connect is disabled during explicit scanning. - * - * @param addr Remote Bluetooth address. - * @param param If non-NULL, auto connect is enabled with the given - * parameters. If NULL, auto connect is disabled. - * - * @return Zero on success or error code otherwise. - */ -__deprecated int bt_le_set_auto_conn(const bt_addr_le_t *addr, - const struct bt_le_conn_param *param); - /** @brief Set security level for a connection. * * This function enable security (encryption) for a connection. If the device @@ -1877,9 +1860,8 @@ struct bt_conn_cb { * start either a connectable advertiser or create a new connection * this might fail because there are no free connection objects * available. - * To avoid this issue it is recommended to either start connectable - * advertise or create a new connection using @ref k_work_submit or - * increase @kconfig{CONFIG_BT_MAX_CONN}. + * To avoid this issue, it's recommended to rely instead on @ref bt_conn_cb.recycled + * which notifies the application when a connection object has actually been freed. * * @param conn Connection object. * @param reason BT_HCI_ERR_* reason for the disconnection. @@ -1891,12 +1873,13 @@ struct bt_conn_cb { * This callback notifies the application that it might be able to * allocate a connection object. No guarantee, first come, first serve. * - * Use this to e.g. re-start connectable advertising or scanning. + * The maximum number of simultaneous connections is configured + * by @kconfig{CONFIG_BT_MAX_CONN}. * - * Treat this callback as an ISR, as it originates from - * @ref bt_conn_unref which is used by the BT stack. Making - * Bluetooth API calls in this context is error-prone and strongly - * discouraged. + * This is the event to listen for to start a new connection or connectable advertiser, + * both when the intention is to start it after the system is completely + * finished with an earlier connection, and when the application wants to start + * a connection for any reason but failed and is waiting for the right time to retry. */ void (*recycled)(void); @@ -2397,8 +2380,8 @@ int bt_le_oob_get_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data **oobd_remote); /** - * Special passkey value that can be used to disable a previously - * set fixed passkey. + * DEPRECATED - use @ref BT_PASSKEY_RAND instead. Special passkey value that can be used to disable + * a previously set fixed passkey. */ #define BT_PASSKEY_INVALID 0xffffffff @@ -2410,12 +2393,15 @@ int bt_le_oob_get_sc_data(struct bt_conn *conn, * Sets a fixed passkey to be used for pairing. If set, the * pairing_confirm() callback will be called for all incoming pairings. * + * @deprecated Use @ref BT_PASSKEY_RAND and the app_passkey callback from @ref bt_conn_auth_cb + * instead. + * * @param passkey A valid passkey (0 - 999999) or BT_PASSKEY_INVALID * to disable a previously set fixed passkey. * * @return 0 on success or a negative error code on failure. */ -int bt_passkey_set(unsigned int passkey); +__deprecated int bt_passkey_set(unsigned int passkey); /** Info Structure for OOB pairing */ struct bt_conn_oob_info { @@ -2481,6 +2467,13 @@ struct bt_conn_pairing_feat { }; #endif /* CONFIG_BT_SMP_APP_PAIRING_ACCEPT */ +/** + * Special passkey value that can be used to generate a random passkey when using the + * app_passkey callback from @ref bt_conn_auth_cb. + * + */ +#define BT_PASSKEY_RAND 0xffffffff + /** Authenticated pairing callback structure */ struct bt_conn_auth_cb { #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT) @@ -2680,6 +2673,30 @@ struct bt_conn_auth_cb { */ void (*pincode_entry)(struct bt_conn *conn, bool highsec); #endif + +#if defined(CONFIG_BT_APP_PASSKEY) + /** @brief Allow the application to provide a passkey for pairing. + * + * If implemented, this callback allows the application to provide passkeys for pairing. + * The valid range of passkeys is 0 - 999999. The application shall return the passkey for + * pairing, or BT_PASSKEY_RAND to generate a random passkey. This callback is invoked only + * for the Passkey Entry method as defined in Core Specification Vol. 3, Part H. Which + * device in the pairing is showing the passkey depends on the IO capabilities of the + * device; see Table 2.8 of the Bluetooth Core Specification V6.0, Vol. 3, Part H for more + * details. For the purposes of this table, the device gains the "display" capability when + * this callback is non-NULL. This is irrespective of whether the callback returns a + * specified key or BT_PASSKEY_RAND. + * + * + * @note When using this callback, it is the responsibility of the application to use + * random and unique keys. + * + * @param conn Connection where pairing is currently active. + * @return Passkey for pairing, or BT_PASSKEY_RAND for the Host to generate a random + * passkey. + */ + uint32_t (*app_passkey)(struct bt_conn *conn); +#endif /* CONFIG_BT_APP_PASSKEY */ }; /** Authenticated pairing information callback structure */ diff --git a/include/zephyr/bluetooth/gap.h b/include/zephyr/bluetooth/gap.h index a6ca5d0ebdc7..b446ad521d4c 100644 --- a/include/zephyr/bluetooth/gap.h +++ b/include/zephyr/bluetooth/gap.h @@ -11,6 +11,7 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_GAP_H_ #define ZEPHYR_INCLUDE_BLUETOOTH_GAP_H_ +#include #include #include @@ -34,682 +35,6 @@ extern "C" { * @} */ -/** - * @name EIR/AD data type definitions - * @{ - */ -#define BT_DATA_FLAGS 0x01 /**< AD flags */ -#define BT_DATA_UUID16_SOME 0x02 /**< 16-bit UUID, more available */ -#define BT_DATA_UUID16_ALL 0x03 /**< 16-bit UUID, all listed */ -#define BT_DATA_UUID32_SOME 0x04 /**< 32-bit UUID, more available */ -#define BT_DATA_UUID32_ALL 0x05 /**< 32-bit UUID, all listed */ -#define BT_DATA_UUID128_SOME 0x06 /**< 128-bit UUID, more available */ -#define BT_DATA_UUID128_ALL 0x07 /**< 128-bit UUID, all listed */ -#define BT_DATA_NAME_SHORTENED 0x08 /**< Shortened name */ -#define BT_DATA_NAME_COMPLETE 0x09 /**< Complete name */ -#define BT_DATA_TX_POWER 0x0a /**< Tx Power */ -#define BT_DATA_DEVICE_CLASS 0x0d /**< Class of Device */ -#define BT_DATA_SIMPLE_PAIRING_HASH_C192 0x0e /**< Simple Pairing Hash C-192 */ -#define BT_DATA_SIMPLE_PAIRING_RAND_C192 0x0f /**< Simple Pairing Randomizer R-192 */ -#define BT_DATA_DEVICE_ID 0x10 /**< Device ID (Profile) */ -#define BT_DATA_SM_TK_VALUE 0x10 /**< Security Manager TK Value */ -#define BT_DATA_SM_OOB_FLAGS 0x11 /**< Security Manager OOB Flags */ -#define BT_DATA_PERIPHERAL_INT_RANGE 0x12 /**< Peripheral Connection Interval Range */ -#define BT_DATA_SOLICIT16 0x14 /**< Solicit UUIDs, 16-bit */ -#define BT_DATA_SOLICIT128 0x15 /**< Solicit UUIDs, 128-bit */ -#define BT_DATA_SVC_DATA16 0x16 /**< Service data, 16-bit UUID */ -#define BT_DATA_PUB_TARGET_ADDR 0x17 /**< Public Target Address */ -#define BT_DATA_RAND_TARGET_ADDR 0x18 /**< Random Target Address */ -#define BT_DATA_GAP_APPEARANCE 0x19 /**< GAP appearance */ -#define BT_DATA_ADV_INT 0x1a /**< Advertising Interval */ -#define BT_DATA_LE_BT_DEVICE_ADDRESS 0x1b /**< LE Bluetooth Device Address */ -#define BT_DATA_LE_ROLE 0x1c /**< LE Role */ -#define BT_DATA_SIMPLE_PAIRING_HASH 0x1d /**< Simple Pairing Hash C256 */ -#define BT_DATA_SIMPLE_PAIRING_RAND 0x1e /**< Simple Pairing Randomizer R256 */ -#define BT_DATA_SOLICIT32 0x1f /**< Solicit UUIDs, 32-bit */ -#define BT_DATA_SVC_DATA32 0x20 /**< Service data, 32-bit UUID */ -#define BT_DATA_SVC_DATA128 0x21 /**< Service data, 128-bit UUID */ -#define BT_DATA_LE_SC_CONFIRM_VALUE 0x22 /**< LE SC Confirmation Value */ -#define BT_DATA_LE_SC_RANDOM_VALUE 0x23 /**< LE SC Random Value */ -#define BT_DATA_URI 0x24 /**< URI */ -#define BT_DATA_INDOOR_POS 0x25 /**< Indoor Positioning */ -#define BT_DATA_TRANS_DISCOVER_DATA 0x26 /**< Transport Discovery Data */ -#define BT_DATA_LE_SUPPORTED_FEATURES 0x27 /**< LE Supported Features */ -#define BT_DATA_CHANNEL_MAP_UPDATE_IND 0x28 /**< Channel Map Update Indication */ -#define BT_DATA_MESH_PROV 0x29 /**< Mesh Provisioning PDU */ -#define BT_DATA_MESH_MESSAGE 0x2a /**< Mesh Networking PDU */ -#define BT_DATA_MESH_BEACON 0x2b /**< Mesh Beacon */ -#define BT_DATA_BIG_INFO 0x2c /**< BIGInfo */ -#define BT_DATA_BROADCAST_CODE 0x2d /**< Broadcast Code */ -#define BT_DATA_CSIS_RSI 0x2e /**< CSIS Random Set ID type */ -#define BT_DATA_ADV_INT_LONG 0x2f /**< Advertising Interval long */ -#define BT_DATA_BROADCAST_NAME 0x30 /**< Broadcast Name */ -#define BT_DATA_ENCRYPTED_AD_DATA 0x31 /**< Encrypted Advertising Data */ -#define BT_DATA_PAWR_TIMING_INFO 0x32 /**< Periodic Advertising Response Timing Info */ -#define BT_DATA_ESL 0x34 /**< Electronic Shelf Label Profile */ -#define BT_DATA_3D_INFO 0x3D /**< 3D Information Data */ - -#define BT_DATA_MANUFACTURER_DATA 0xff /**< Manufacturer Specific Data */ - -#define BT_LE_AD_LIMITED 0x01 /**< Limited Discoverable */ -#define BT_LE_AD_GENERAL 0x02 /**< General Discoverable */ -#define BT_LE_AD_NO_BREDR 0x04 /**< BR/EDR not supported */ -/** - * @} - */ - -/** - * @name Appearance Values - * - * Last Modified on 2023-01-05 - * @{ - */ -/** Generic Unknown */ -#define BT_APPEARANCE_UNKNOWN 0x0000 -/** Generic Phone */ -#define BT_APPEARANCE_GENERIC_PHONE 0x0040 -/** Generic Computer */ -#define BT_APPEARANCE_GENERIC_COMPUTER 0x0080 -/** Desktop Workstation */ -#define BT_APPEARANCE_COMPUTER_DESKTOP_WORKSTATION 0x0081 -/** Server-class Computer */ -#define BT_APPEARANCE_COMPUTER_SERVER_CLASS 0x0082 -/** Laptop */ -#define BT_APPEARANCE_COMPUTER_LAPTOP 0x0083 -/** Handheld PC/PDA (clamshell) */ -#define BT_APPEARANCE_COMPUTER_HANDHELD_PCPDA 0x0084 -/** Palm­size PC/PDA */ -#define BT_APPEARANCE_COMPUTER_PALMSIZE_PCPDA 0x0085 -/** Wearable computer (watch size) */ -#define BT_APPEARANCE_COMPUTER_WEARABLE_COMPUTER 0x0086 -/** Tablet */ -#define BT_APPEARANCE_COMPUTER_TABLET 0x0087 -/** Docking Station */ -#define BT_APPEARANCE_COMPUTER_DOCKING_STATION 0x0088 -/** All in One */ -#define BT_APPEARANCE_COMPUTER_ALL_IN_ONE 0x0089 -/** Blade Server */ -#define BT_APPEARANCE_COMPUTER_BLADE_SERVER 0x008A -/** Convertible */ -#define BT_APPEARANCE_COMPUTER_CONVERTIBLE 0x008B -/** Detachable */ -#define BT_APPEARANCE_COMPUTER_DETACHABLE 0x008C -/** IoT Gateway */ -#define BT_APPEARANCE_COMPUTER_IOT_GATEWAY 0x008D -/** Mini PC */ -#define BT_APPEARANCE_COMPUTER_MINI_PC 0x008E -/** Stick PC */ -#define BT_APPEARANCE_COMPUTER_STICK_PC 0x008F -/** Generic Watch */ -#define BT_APPEARANCE_GENERIC_WATCH 0x00C0 -/** Sports Watch */ -#define BT_APPEARANCE_SPORTS_WATCH 0x00C1 -/** Smartwatch */ -#define BT_APPEARANCE_SMARTWATCH 0x00C2 -/** Generic Clock */ -#define BT_APPEARANCE_GENERIC_CLOCK 0x0100 -/** Generic Display */ -#define BT_APPEARANCE_GENERIC_DISPLAY 0x0140 -/** Generic Remote Control */ -#define BT_APPEARANCE_GENERIC_REMOTE 0x0180 -/** Generic Eye-glasses */ -#define BT_APPEARANCE_GENERIC_EYEGLASSES 0x01C0 -/** Generic Tag */ -#define BT_APPEARANCE_GENERIC_TAG 0x0200 -/** Generic Keyring */ -#define BT_APPEARANCE_GENERIC_KEYRING 0x0240 -/** Generic Media Player */ -#define BT_APPEARANCE_GENERIC_MEDIA_PLAYER 0x0280 -/** Generic Barcode Scanner */ -#define BT_APPEARANCE_GENERIC_BARCODE_SCANNER 0x02C0 -/** Generic Thermometer */ -#define BT_APPEARANCE_GENERIC_THERMOMETER 0x0300 -/** Ear Thermometer */ -#define BT_APPEARANCE_THERMOMETER_EAR 0x0301 -/** Generic Heart Rate Sensor */ -#define BT_APPEARANCE_GENERIC_HEART_RATE 0x0340 -/** Heart Rate Belt */ -#define BT_APPEARANCE_HEART_RATE_BELT 0x0341 -/** Generic Blood Pressure */ -#define BT_APPEARANCE_GENERIC_BLOOD_PRESSURE 0x0380 -/** Arm Blood Pressure */ -#define BT_APPEARANCE_BLOOD_PRESSURE_ARM 0x0381 -/** Wrist Blood Pressure */ -#define BT_APPEARANCE_BLOOD_PRESSURE_WRIST 0x0382 -/** Generic Human Interface Device */ -#define BT_APPEARANCE_GENERIC_HID 0x03C0 -/** Keyboard */ -#define BT_APPEARANCE_HID_KEYBOARD 0x03C1 -/** Mouse */ -#define BT_APPEARANCE_HID_MOUSE 0x03C2 -/** Joystick */ -#define BT_APPEARANCE_HID_JOYSTICK 0x03C3 -/** Gamepad */ -#define BT_APPEARANCE_HID_GAMEPAD 0x03C4 -/** Digitizer Tablet */ -#define BT_APPEARANCE_HID_DIGITIZER_TABLET 0x03C5 -/** Card Reader */ -#define BT_APPEARANCE_HID_CARD_READER 0x03C6 -/** Digital Pen */ -#define BT_APPEARANCE_HID_DIGITAL_PEN 0x03C7 -/** Barcode Scanner */ -#define BT_APPEARANCE_HID_BARCODE_SCANNER 0x03C8 -/** Touchpad */ -#define BT_APPEARANCE_HID_TOUCHPAD 0x03C9 -/** Presentation Remote */ -#define BT_APPEARANCE_HID_PRESENTATION_REMOTE 0x03CA -/** Generic Glucose Meter */ -#define BT_APPEARANCE_GENERIC_GLUCOSE 0x0400 -/** Generic Running Walking Sensor */ -#define BT_APPEARANCE_GENERIC_WALKING 0x0440 -/** In-Shoe Running Walking Sensor */ -#define BT_APPEARANCE_WALKING_IN_SHOE 0x0441 -/** On-Shoe Running Walking Sensor */ -#define BT_APPEARANCE_WALKING_ON_SHOE 0x0442 -/** On-Hip Running Walking Sensor */ -#define BT_APPEARANCE_WALKING_ON_HIP 0x0443 -/** Generic Cycling */ -#define BT_APPEARANCE_GENERIC_CYCLING 0x0480 -/** Cycling Computer */ -#define BT_APPEARANCE_CYCLING_COMPUTER 0x0481 -/** Speed Sensor */ -#define BT_APPEARANCE_CYCLING_SPEED 0x0482 -/** Cadence Sensor */ -#define BT_APPEARANCE_CYCLING_CADENCE 0x0483 -/** Power Sensor */ -#define BT_APPEARANCE_CYCLING_POWER 0x0484 -/** Speed and Cadence Sensor */ -#define BT_APPEARANCE_CYCLING_SPEED_CADENCE 0x0485 -/** Generic Control Device */ -#define BT_APPEARANCE_GENERIC_CONTROL_DEVICE 0x04C0 -/** Switch */ -#define BT_APPEARANCE_CONTROL_SWITCH 0x04C1 -/** Multi-switch */ -#define BT_APPEARANCE_CONTROL_MULTI_SWITCH 0x04C2 -/** Button */ -#define BT_APPEARANCE_CONTROL_BUTTON 0x04C3 -/** Slider */ -#define BT_APPEARANCE_CONTROL_SLIDER 0x04C4 -/** Rotary Switch */ -#define BT_APPEARANCE_CONTROL_ROTARY_SWITCH 0x04C5 -/** Touch Panel */ -#define BT_APPEARANCE_CONTROL_TOUCH_PANEL 0x04C6 -/** Single Switch */ -#define BT_APPEARANCE_CONTROL_SINGLE_SWITCH 0x04C7 -/** Double Switch */ -#define BT_APPEARANCE_CONTROL_DOUBLE_SWITCH 0x04C8 -/** Triple Switch */ -#define BT_APPEARANCE_CONTROL_TRIPLE_SWITCH 0x04C9 -/** Battery Switch */ -#define BT_APPEARANCE_CONTROL_BATTERY_SWITCH 0x04CA -/** Energy Harvesting Switch */ -#define BT_APPEARANCE_CONTROL_ENERGY_HARVESTING_SWITCH 0x04CB -/** Push Button */ -#define BT_APPEARANCE_CONTROL_PUSH_BUTTON 0x04CC -/** Generic Network Device */ -#define BT_APPEARANCE_GENERIC_NETWORK_DEVICE 0x0500 -/** Access Point */ -#define BT_APPEARANCE_NETWORK_ACCESS_POINT 0x0501 -/** Mesh Device */ -#define BT_APPEARANCE_NETWORK_MESH_DEVICE 0x0502 -/** Mesh Network Proxy */ -#define BT_APPEARANCE_NETWORK_MESH_PROXY 0x0503 -/** Generic Sensor */ -#define BT_APPEARANCE_GENERIC_SENSOR 0x0540 -/** Motion Sensor */ -#define BT_APPEARANCE_SENSOR_MOTION 0x0541 -/** Air quality Sensor */ -#define BT_APPEARANCE_SENSOR_AIR_QUALITY 0x0542 -/** Temperature Sensor */ -#define BT_APPEARANCE_SENSOR_TEMPERATURE 0x0543 -/** Humidity Sensor */ -#define BT_APPEARANCE_SENSOR_HUMIDITY 0x0544 -/** Leak Sensor */ -#define BT_APPEARANCE_SENSOR_LEAK 0x0545 -/** Smoke Sensor */ -#define BT_APPEARANCE_SENSOR_SMOKE 0x0546 -/** Occupancy Sensor */ -#define BT_APPEARANCE_SENSOR_OCCUPANCY 0x0547 -/** Contact Sensor */ -#define BT_APPEARANCE_SENSOR_CONTACT 0x0548 -/** Carbon Monoxide Sensor */ -#define BT_APPEARANCE_SENSOR_CARBON_MONOXIDE 0x0549 -/** Carbon Dioxide Sensor */ -#define BT_APPEARANCE_SENSOR_CARBON_DIOXIDE 0x054A -/** Ambient Light Sensor */ -#define BT_APPEARANCE_SENSOR_AMBIENT_LIGHT 0x054B -/** Energy Sensor */ -#define BT_APPEARANCE_SENSOR_ENERGY 0x054C -/** Color Light Sensor */ -#define BT_APPEARANCE_SENSOR_COLOR_LIGHT 0x054D -/** Rain Sensor */ -#define BT_APPEARANCE_SENSOR_RAIN 0x054E -/** Fire Sensor */ -#define BT_APPEARANCE_SENSOR_FIRE 0x054F -/** Wind Sensor */ -#define BT_APPEARANCE_SENSOR_WIND 0x0550 -/** Proximity Sensor */ -#define BT_APPEARANCE_SENSOR_PROXIMITY 0x0551 -/** Multi-Sensor */ -#define BT_APPEARANCE_SENSOR_MULTI 0x0552 -/** Flush Mounted Sensor */ -#define BT_APPEARANCE_SENSOR_FLUSH_MOUNTED 0x0553 -/** Ceiling Mounted Sensor */ -#define BT_APPEARANCE_SENSOR_CEILING_MOUNTED 0x0554 -/** Wall Mounted Sensor */ -#define BT_APPEARANCE_SENSOR_WALL_MOUNTED 0x0555 -/** Multisensor */ -#define BT_APPEARANCE_MULTISENSOR 0x0556 -/** Energy Meter */ -#define BT_APPEARANCE_SENSOR_ENERGY_METER 0x0557 -/** Flame Detector */ -#define BT_APPEARANCE_SENSOR_FLAME_DETECTOR 0x0558 -/** Vehicle Tire Pressure Sensor */ -#define BT_APPEARANCE_SENSOR_VEHICLE_TIRE_PRESSURE 0x0559 -/** Generic Light Fixtures */ -#define BT_APPEARANCE_GENERIC_LIGHT_FIXTURES 0x0580 -/** Wall Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_WALL 0x0581 -/** Ceiling Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_CEILING 0x0582 -/** Floor Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_FLOOR 0x0583 -/** Cabinet Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_CABINET 0x0584 -/** Desk Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_DESK 0x0585 -/** Troffer Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_TROFFER 0x0586 -/** Pendant Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_PENDANT 0x0587 -/** In-ground Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_IN_GROUND 0x0588 -/** Flood Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_FLOOD 0x0589 -/** Underwater Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_UNDERWATER 0x058A -/** Bollard with Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_BOLLARD_WITH 0x058B -/** Pathway Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_PATHWAY 0x058C -/** Garden Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_GARDEN 0x058D -/** Pole-top Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_POLE_TOP 0x058E -/** Spotlight */ -#define BT_APPEARANCE_SPOT_LIGHT 0x058F -/** Linear Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_LINEAR 0x0590 -/** Street Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_STREET 0x0591 -/** Shelves Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_SHELVES 0x0592 -/** Bay Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_BAY 0x0593 -/** Emergency Exit Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_EMERGENCY_EXIT 0x0594 -/** Light Controller */ -#define BT_APPEARANCE_LIGHT_FIXTURES_CONTROLLER 0x0595 -/** Light Driver */ -#define BT_APPEARANCE_LIGHT_FIXTURES_DRIVER 0x0596 -/** Bulb */ -#define BT_APPEARANCE_LIGHT_FIXTURES_BULB 0x0597 -/** Low-bay Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_LOW_BAY 0x0598 -/** High-bay Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_HIGH_BAY 0x0599 -/** Generic Fan */ -#define BT_APPEARANCE_GENERIC_FAN 0x05C0 -/** Ceiling Fan */ -#define BT_APPEARANCE_FAN_CEILING 0x05C1 -/** Axial Fan */ -#define BT_APPEARANCE_FAN_AXIAL 0x05C2 -/** Exhaust Fan */ -#define BT_APPEARANCE_FAN_EXHAUST 0x05C3 -/** Pedestal Fan */ -#define BT_APPEARANCE_FAN_PEDESTAL 0x05C4 -/** Desk Fan */ -#define BT_APPEARANCE_FAN_DESK 0x05C5 -/** Wall Fan */ -#define BT_APPEARANCE_FAN_WALL 0x05C6 -/** Generic HVAC */ -#define BT_APPEARANCE_GENERIC_HVAC 0x0600 -/** Thermostat */ -#define BT_APPEARANCE_HVAC_THERMOSTAT 0x0601 -/** Humidifier */ -#define BT_APPEARANCE_HVAC_HUMIDIFIER 0x0602 -/** De-humidifier */ -#define BT_APPEARANCE_HVAC_DEHUMIDIFIER 0x0603 -/** Heater */ -#define BT_APPEARANCE_HVAC_HEATER 0x0604 -/** Radiator */ -#define BT_APPEARANCE_HVAC_RADIATOR 0x0605 -/** Boiler */ -#define BT_APPEARANCE_HVAC_BOILER 0x0606 -/** Heat Pump */ -#define BT_APPEARANCE_HVAC_HEAT_PUMP 0x0607 -/** Infrared Heater */ -#define BT_APPEARANCE_HVAC_INFRARED_HEATER 0x0608 -/** Radiant Panel Heater */ -#define BT_APPEARANCE_HVAC_RADIANT_PANEL_HEATER 0x0609 -/** Fan Heater */ -#define BT_APPEARANCE_HVAC_FAN_HEATER 0x060A -/** Air Curtain */ -#define BT_APPEARANCE_HVAC_AIR_CURTAIN 0x060B -/** Generic Air Conditioning */ -#define BT_APPEARANCE_GENERIC_AIR_CONDITIONING 0x0640 -/** Generic Humidifier */ -#define BT_APPEARANCE_GENERIC_HUMIDIFIER 0x0680 -/** Generic Heating */ -#define BT_APPEARANCE_GENERIC_HEATING 0x06C0 -/** Radiator */ -#define BT_APPEARANCE_HEATING_RADIATOR 0x06C1 -/** Boiler */ -#define BT_APPEARANCE_HEATING_BOILER 0x06C2 -/** Heat Pump */ -#define BT_APPEARANCE_HEATING_HEAT_PUMP 0x06C3 -/** Infrared Heater */ -#define BT_APPEARANCE_HEATING_INFRARED_HEATER 0x06C4 -/** Radiant Panel Heater */ -#define BT_APPEARANCE_HEATING_RADIANT_PANEL_HEATER 0x06C5 -/** Fan Heater */ -#define BT_APPEARANCE_HEATING_FAN_HEATER 0x06C6 -/** Air Curtain */ -#define BT_APPEARANCE_HEATING_AIR_CURTAIN 0x06C7 -/** Generic Access Control */ -#define BT_APPEARANCE_GENERIC_ACCESS_CONTROL 0x0700 -/** Access Door */ -#define BT_APPEARANCE_CONTROL_ACCESS_DOOR 0x0701 -/** Garage Door */ -#define BT_APPEARANCE_CONTROL_GARAGE_DOOR 0x0702 -/** Emergency Exit Door */ -#define BT_APPEARANCE_CONTROL_EMERGENCY_EXIT_DOOR 0x0703 -/** Access Lock */ -#define BT_APPEARANCE_CONTROL_ACCESS_LOCK 0x0704 -/** Elevator */ -#define BT_APPEARANCE_CONTROL_ELEVATOR 0x0705 -/** Window */ -#define BT_APPEARANCE_CONTROL_WINDOW 0x0706 -/** Entrance Gate */ -#define BT_APPEARANCE_CONTROL_ENTRANCE_GATE 0x0707 -/** Door Lock */ -#define BT_APPEARANCE_CONTROL_DOOR_LOCK 0x0708 -/** Locker */ -#define BT_APPEARANCE_CONTROL_LOCKER 0x0709 -/** Generic Motorized Device */ -#define BT_APPEARANCE_GENERIC_MOTORIZED_DEVICE 0x0740 -/** Motorized Gate */ -#define BT_APPEARANCE_MOTORIZED_GATE 0x0741 -/** Awning */ -#define BT_APPEARANCE_MOTORIZED_AWNING 0x0742 -/** Blinds or Shades */ -#define BT_APPEARANCE_MOTORIZED_BLINDS_OR_SHADES 0x0743 -/** Curtains */ -#define BT_APPEARANCE_MOTORIZED_CURTAINS 0x0744 -/** Screen */ -#define BT_APPEARANCE_MOTORIZED_SCREEN 0x0745 -/** Generic Power Device */ -#define BT_APPEARANCE_GENERIC_POWER_DEVICE 0x0780 -/** Power Outlet */ -#define BT_APPEARANCE_POWER_OUTLET 0x0781 -/** Power Strip */ -#define BT_APPEARANCE_POWER_STRIP 0x0782 -/** Plug */ -#define BT_APPEARANCE_POWER_PLUG 0x0783 -/** Power Supply */ -#define BT_APPEARANCE_POWER_SUPPLY 0x0784 -/** LED Driver */ -#define BT_APPEARANCE_POWER_LED_DRIVER 0x0785 -/** Fluorescent Lamp Gear */ -#define BT_APPEARANCE_POWER_FLUORESCENT_LAMP_GEAR 0x0786 -/** HID Lamp Gear */ -#define BT_APPEARANCE_POWER_HID_LAMP_GEAR 0x0787 -/** Charge Case */ -#define BT_APPEARANCE_POWER_CHARGE_CASE 0x0788 -/** Power Bank */ -#define BT_APPEARANCE_POWER_POWER_BANK 0x0789 -/** Generic Light Source */ -#define BT_APPEARANCE_GENERIC_LIGHT_SOURCE 0x07C0 -/** Incandescent Light Bulb */ -#define BT_APPEARANCE_LIGHT_SOURCE_INCANDESCENT_BULB 0x07C1 -/** LED Lamp */ -#define BT_APPEARANCE_LIGHT_SOURCE_LED_LAMP 0x07C2 -/** HID Lamp */ -#define BT_APPEARANCE_LIGHT_SOURCE_HID_LAMP 0x07C3 -/** Fluorescent Lamp */ -#define BT_APPEARANCE_LIGHT_SOURCE_FLUORESCENT_LAMP 0x07C4 -/** LED Array */ -#define BT_APPEARANCE_LIGHT_SOURCE_LED_ARRAY 0x07C5 -/** Multi-Color LED Array */ -#define BT_APPEARANCE_LIGHT_SOURCE_MULTICOLOR_LED_ARRAY 0x07C6 -/** Low voltage halogen */ -#define BT_APPEARANCE_LIGHT_SOURCE_LOW_VOLTAGE_HALOGEN 0x07C7 -/** Organic light emitting diode */ -#define BT_APPEARANCE_LIGHT_SOURCE_OLED 0x07C8 -/** Generic Window Covering */ -#define BT_APPEARANCE_GENERIC_WINDOW_COVERING 0x0800 -/** Window Shades */ -#define BT_APPEARANCE_WINDOW_SHADES 0x0801 -/** Window Blinds */ -#define BT_APPEARANCE_WINDOW_BLINDS 0x0802 -/** Window Awning */ -#define BT_APPEARANCE_WINDOW_AWNING 0x0803 -/** Window Curtain */ -#define BT_APPEARANCE_WINDOW_CURTAIN 0x0804 -/** Exterior Shutter */ -#define BT_APPEARANCE_WINDOW_EXTERIOR_SHUTTER 0x0805 -/** Exterior Screen */ -#define BT_APPEARANCE_WINDOW_EXTERIOR_SCREEN 0x0806 -/** Generic Audio Sink */ -#define BT_APPEARANCE_GENERIC_AUDIO_SINK 0x0840 -/** Standalone Speaker */ -#define BT_APPEARANCE_AUDIO_SINK_STANDALONE_SPEAKER 0x0841 -/** Soundbar */ -#define BT_APPEARANCE_AUDIO_SINK_SOUNDBAR 0x0842 -/** Bookshelf Speaker */ -#define BT_APPEARANCE_AUDIO_SINK_BOOKSHELF_SPEAKER 0x0843 -/** Standmounted Speaker */ -#define BT_APPEARANCE_AUDIO_SINK_STANDMOUNTED_SPEAKER 0x0844 -/** Speakerphone */ -#define BT_APPEARANCE_AUDIO_SINK_SPEAKERPHONE 0x0845 -/** Generic Audio Source */ -#define BT_APPEARANCE_GENERIC_AUDIO_SOURCE 0x0880 -/** Microphone */ -#define BT_APPEARANCE_AUDIO_SOURCE_MICROPHONE 0x0881 -/** Alarm */ -#define BT_APPEARANCE_AUDIO_SOURCE_ALARM 0x0882 -/** Bell */ -#define BT_APPEARANCE_AUDIO_SOURCE_BELL 0x0883 -/** Horn */ -#define BT_APPEARANCE_AUDIO_SOURCE_HORN 0x0884 -/** Broadcasting Device */ -#define BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE 0x0885 -/** Service Desk */ -#define BT_APPEARANCE_AUDIO_SOURCE_SERVICE_DESK 0x0886 -/** Kiosk */ -#define BT_APPEARANCE_AUDIO_SOURCE_KIOSK 0x0887 -/** Broadcasting Room */ -#define BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_ROOM 0x0888 -/** Auditorium */ -#define BT_APPEARANCE_AUDIO_SOURCE_AUDITORIUM 0x0889 -/** Generic Motorized Vehicle */ -#define BT_APPEARANCE_GENERIC_MOTORIZED_VEHICLE 0x08C0 -/** Car */ -#define BT_APPEARANCE_VEHICLE_CAR 0x08C1 -/** Large Goods Vehicle */ -#define BT_APPEARANCE_VEHICLE_LARGE_GOODS 0x08C2 -/** 2-Wheeled Vehicle */ -#define BT_APPEARANCE_VEHICLE_TWO_WHEELED 0x08C3 -/** Motorbike */ -#define BT_APPEARANCE_VEHICLE_MOTORBIKE 0x08C4 -/** Scooter */ -#define BT_APPEARANCE_VEHICLE_SCOOTER 0x08C5 -/** Moped */ -#define BT_APPEARANCE_VEHICLE_MOPED 0x08C6 -/** 3-Wheeled Vehicle */ -#define BT_APPEARANCE_VEHICLE_THREE_WHEELED 0x08C7 -/** Light Vehicle */ -#define BT_APPEARANCE_VEHICLE_LIGHT 0x08C8 -/** Quad Bike */ -#define BT_APPEARANCE_VEHICLE_QUAD_BIKE 0x08C9 -/** Minibus */ -#define BT_APPEARANCE_VEHICLE_MINIBUS 0x08CA -/** Bus */ -#define BT_APPEARANCE_VEHICLE_BUS 0x08CB -/** Trolley */ -#define BT_APPEARANCE_VEHICLE_TROLLEY 0x08CC -/** Agricultural Vehicle */ -#define BT_APPEARANCE_VEHICLE_AGRICULTURAL 0x08CD -/** Camper/Caravan */ -#define BT_APPEARANCE_VEHICLE_CAMPER_OR_CARAVAN 0x08CE -/** Recreational Vehicle/Motor Home */ -#define BT_APPEARANCE_VEHICLE_RECREATIONAL 0x08CF -/** Generic Domestic Appliance */ -#define BT_APPEARANCE_GENERIC_DOMESTIC_APPLIANCE 0x0900 -/** Refrigerator */ -#define BT_APPEARANCE_APPLIANCE_REFRIGERATOR 0x0901 -/** Freezer */ -#define BT_APPEARANCE_APPLIANCE_FREEZER 0x0902 -/** Oven */ -#define BT_APPEARANCE_APPLIANCE_OVEN 0x0903 -/** Microwave */ -#define BT_APPEARANCE_APPLIANCE_MICROWAVE 0x0904 -/** Toaster */ -#define BT_APPEARANCE_APPLIANCE_TOASTER 0x0905 -/** Washing Machine */ -#define BT_APPEARANCE_APPLIANCE_WASHING_MACHINE 0x0906 -/** Dryer */ -#define BT_APPEARANCE_APPLIANCE_DRYER 0x0907 -/** Coffee maker */ -#define BT_APPEARANCE_APPLIANCE_COFFEE_MAKER 0x0908 -/** Clothes iron */ -#define BT_APPEARANCE_APPLIANCE_CLOTHES_IRON 0x0909 -/** Curling iron */ -#define BT_APPEARANCE_APPLIANCE_CURLING_IRON 0x090A -/** Hair dryer */ -#define BT_APPEARANCE_APPLIANCE_HAIR_DRYER 0x090B -/** Vacuum cleaner */ -#define BT_APPEARANCE_APPLIANCE_VACUUM_CLEANER 0x090C -/** Robotic vacuum cleaner */ -#define BT_APPEARANCE_APPLIANCE_ROBOTIC_VACUUM_CLEANER 0x090D -/** Rice cooker */ -#define BT_APPEARANCE_APPLIANCE_RICE_COOKER 0x090E -/** Clothes steamer */ -#define BT_APPEARANCE_APPLIANCE_CLOTHES_STEAMER 0x090F -/** Generic Wearable Audio Device */ -#define BT_APPEARANCE_GENERIC_WEARABLE_AUDIO_DEVICE 0x0940 -/** Earbud */ -#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_EARBUD 0x0941 -/** Headset */ -#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADSET 0x0942 -/** Headphones */ -#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADPHONES 0x0943 -/** Neck Band */ -#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_NECK_BAND 0x0944 -/** Generic Aircraft */ -#define BT_APPEARANCE_GENERIC_AIRCRAFT 0x0980 -/** Light Aircraft */ -#define BT_APPEARANCE_AIRCRAFT_LIGHT 0x0981 -/** Microlight */ -#define BT_APPEARANCE_AIRCRAFT_MICROLIGHT 0x0982 -/** Paraglider */ -#define BT_APPEARANCE_AIRCRAFT_PARAGLIDER 0x0983 -/** Large Passenger Aircraft */ -#define BT_APPEARANCE_AIRCRAFT_LARGE_PASSENGER 0x0984 -/** Generic AV Equipment */ -#define BT_APPEARANCE_GENERIC_AV_EQUIPMENT 0x09C0 -/** Amplifier */ -#define BT_APPEARANCE_AV_EQUIPMENT_AMPLIFIER 0x09C1 -/** Receiver */ -#define BT_APPEARANCE_AV_EQUIPMENT_RECEIVER 0x09C2 -/** Radio */ -#define BT_APPEARANCE_AV_EQUIPMENT_RADIO 0x09C3 -/** Tuner */ -#define BT_APPEARANCE_AV_EQUIPMENT_TUNER 0x09C4 -/** Turntable */ -#define BT_APPEARANCE_AV_EQUIPMENT_TURNTABLE 0x09C5 -/** CD Player */ -#define BT_APPEARANCE_AV_EQUIPMENT_CD_PLAYER 0x09C6 -/** DVD Player */ -#define BT_APPEARANCE_AV_EQUIPMENT_DVD_PLAYER 0x09C7 -/** Bluray Player */ -#define BT_APPEARANCE_AV_EQUIPMENT_BLURAY_PLAYER 0x09C8 -/** Optical Disc Player */ -#define BT_APPEARANCE_AV_EQUIPMENT_OPTICAL_DISC_PLAYER 0x09C9 -/** Set-Top Box */ -#define BT_APPEARANCE_AV_EQUIPMENT_SET_TOP_BOX 0x09CA -/** Generic Display Equipment */ -#define BT_APPEARANCE_GENERIC_DISPLAY_EQUIPMENT 0x0A00 -/** Television */ -#define BT_APPEARANCE_DISPLAY_EQUIPMENT_TELEVISION 0x0A01 -/** Monitor */ -#define BT_APPEARANCE_DISPLAY_EQUIPMENT_MONITOR 0x0A02 -/** Projector */ -#define BT_APPEARANCE_DISPLAY_EQUIPMENT_PROJECTOR 0x0A03 -/** Generic Hearing aid */ -#define BT_APPEARANCE_GENERIC_HEARING_AID 0x0A40 -/** In-ear hearing aid */ -#define BT_APPEARANCE_HEARING_AID_IN_EAR 0x0A41 -/** Behind-ear hearing aid */ -#define BT_APPEARANCE_HEARING_AID_BEHIND_EAR 0x0A42 -/** Cochlear Implant */ -#define BT_APPEARANCE_HEARING_AID_COCHLEAR_IMPLANT 0x0A43 -/** Generic Gaming */ -#define BT_APPEARANCE_GENERIC_GAMING 0x0A80 -/** Home Video Game Console */ -#define BT_APPEARANCE_HOME_VIDEO_GAME_CONSOLE 0x0A81 -/** Portable handheld console */ -#define BT_APPEARANCE_PORTABLE_HANDHELD_CONSOLE 0x0A82 -/** Generic Signage */ -#define BT_APPEARANCE_GENERIC_SIGNAGE 0x0AC0 -/** Digital Signage */ -#define BT_APPEARANCE_SIGNAGE_DIGITAL 0x0AC1 -/** Electronic Label */ -#define BT_APPEARANCE_SIGNAGE_ELECTRONIC_LABEL 0x0AC2 -/** Generic Pulse Oximeter */ -#define BT_APPEARANCE_GENERIC_PULSE_OXIMETER 0x0C40 -/** Fingertip Pulse Oximeter */ -#define BT_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41 -/** Wrist Worn Pulse Oximeter */ -#define BT_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42 -/** Generic Weight Scale */ -#define BT_APPEARANCE_GENERIC_WEIGHT_SCALE 0x0C80 -/** Generic Personal Mobility Device */ -#define BT_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE 0x0CC0 -/** Powered Wheelchair */ -#define BT_APPEARANCE_MOBILITY_POWERED_WHEELCHAIR 0x0CC1 -/** Mobility Scooter */ -#define BT_APPEARANCE_MOBILITY_SCOOTER 0x0CC2 -/** Continuous Glucose Monitor */ -#define BT_APPEARANCE_CONTINUOUS_GLUCOSE_MONITOR 0x0D00 -/** Generic Insulin Pump */ -#define BT_APPEARANCE_GENERIC_INSULIN_PUMP 0x0D40 -/** Insulin Pump, durable pump */ -#define BT_APPEARANCE_INSULIN_PUMP_DURABLE 0x0D41 -/** Insulin Pump, patch pump */ -#define BT_APPEARANCE_INSULIN_PUMP_PATCH 0x0D44 -/** Insulin Pen */ -#define BT_APPEARANCE_INSULIN_PEN 0x0D48 -/** Generic Medication Delivery */ -#define BT_APPEARANCE_GENERIC_MEDICATION_DELIVERY 0x0D80 -/** Generic Spirometer */ -#define BT_APPEARANCE_GENERIC_SPIROMETER 0x0DC0 -/** Handheld Spirometer */ -#define BT_APPEARANCE_SPIROMETER_HANDHELD 0x0DC1 -/** Generic Outdoor Sports Activity */ -#define BT_APPEARANCE_GENERIC_OUTDOOR_SPORTS 0x1440 -/** Location Display */ -#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION 0x1441 -/** Location and Navigation Display */ -#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV 0x1442 -/** Location Pod */ -#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD 0x1443 -/** Location and Navigation Pod */ -#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV 0x1444 -/** - * @} - */ - /** * @name Defined GAP timers * @{ diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index cd6c716c1cbe..d520a2324266 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -913,6 +913,7 @@ struct bt_hci_rp_configure_data_path { #define BT_HCI_VERSION_5_4 13 #define BT_HCI_VERSION_6_0 14 #define BT_HCI_VERSION_6_1 15 +#define BT_HCI_VERSION_6_2 16 #define BT_HCI_OP_READ_LOCAL_VERSION_INFO BT_OP(BT_OGF_INFO, 0x0001) /* 0x1001 */ struct bt_hci_rp_read_local_version_info { diff --git a/include/zephyr/bluetooth/hci_vs.h b/include/zephyr/bluetooth/hci_vs.h index 1170c41474a2..904bcbdb2d5d 100644 --- a/include/zephyr/bluetooth/hci_vs.h +++ b/include/zephyr/bluetooth/hci_vs.h @@ -222,20 +222,20 @@ struct bt_hci_evt_vs { uint8_t subevent; } __packed; -#define BT_HCI_EVT_VS_FATAL_ERROR 0x02 - #define BT_HCI_EVT_VS_ERROR_DATA_TYPE_STACK_FRAME 0x01 #define BT_HCI_EVT_VS_ERROR_DATA_TYPE_CTRL_ASSERT 0x02 #define BT_HCI_EVT_VS_ERROR_DATA_TYPE_TRACE 0x03 -struct bt_hci_vs_fata_error_cpu_data_cortex_m { +struct bt_hci_vs_fatal_error_cpu_data_cortex_m { uint32_t a1; uint32_t a2; uint32_t a3; uint32_t a4; uint32_t ip; uint32_t lr; + uint32_t pc; uint32_t xpsr; } __packed; + #define BT_HCI_EVT_VS_ERROR_CPU_TYPE_CORTEX_M 0x01 struct bt_hci_vs_fatal_error_stack_frame { uint32_t reason; diff --git a/include/zephyr/bluetooth/l2cap.h b/include/zephyr/bluetooth/l2cap.h index 571b57e76ac9..0ffa85bc41c6 100644 --- a/include/zephyr/bluetooth/l2cap.h +++ b/include/zephyr/bluetooth/l2cap.h @@ -139,6 +139,27 @@ extern "C" { */ #define BT_L2CAP_ECRED_CHAN_MAX_PER_REQ 5 +/** + * @defgroup l2cap_cid L2CAP channel identifiers + * @ingroup bt_l2cap + * @{ + * + * @brief Standard L2CAP channel identifiers + */ + +/** @brief BR signaling channel */ +#define BT_L2CAP_CID_BR_SIG 0x0001 +/** @brief Attribute Protocol channel */ +#define BT_L2CAP_CID_ATT 0x0004 +/** @brief LE signaling channel */ +#define BT_L2CAP_CID_LE_SIG 0x0005 +/** @brief Security Manager Protocol channel */ +#define BT_L2CAP_CID_SMP 0x0006 +/** @brief BR Security Manager Protocol channel */ +#define BT_L2CAP_CID_BR_SMP 0x0007 + +/** @} */ + struct bt_l2cap_chan; /** @typedef bt_l2cap_chan_destroy_t @@ -290,6 +311,68 @@ struct bt_l2cap_le_chan { */ #define BT_L2CAP_LE_CHAN(_ch) CONTAINER_OF(_ch, struct bt_l2cap_le_chan, chan) +/** @brief Fixed L2CAP Channel structure. Should be defined using the + * @ref BT_L2CAP_FIXED_CHANNEL_DEFINE macro. + */ +struct bt_l2cap_fixed_chan { + /** @brief Channel Identifier (CID) + * + * @note Shall be in the range 0x0001 to 0x003F (Core 3.A.2.1 v6.0). The CIDs in this range + * are reserved by the stack, so the application needs to make sure that the CID is + * not already in use. Table 2.1 in Core 3.A.2.1 and @ref l2cap_cid shows the + * CIDs used by the stack. + */ + uint16_t cid; + + /** @brief Channel accept callback + * + * This callback needs to be provided by the application, and is invoked when a new + * connection has been established. If accepting the connection, the user is expected to + * allocate memory with suitable alignment for the type @ref bt_l2cap_chan for the channel, + * and update the channel reference @p chan to point to the allocated memory. The channel + * should be initialized by assigning the callbacks to the @ref bt_l2cap_chan_ops field + * as follows: + * @code + * static int accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) + * { + * // Allocation of fixed_chan and definition of the ops are assumed done prior. + * *chan = &fixed_chan; + * + * **chan = (struct bt_l2cap_chan){ + * .ops = &ops, + * }; + * + * return 0; + * } + * @endcode + * The allocated context needs to be valid for the lifetime of the channel, i. e. + * freeing of the memory can be done in the @ref bt_l2cap_chan_ops.released callback. + * + * @param conn The connection that has been established. + * @param chan L2CAP channel reference. + * + * @return 0 to accept the channel connection, negative error code otherwise. + */ + int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan); +}; + +/** + * @brief Register a fixed L2CAP channel. + * + * Define and register a fixed L2CAP channel of type @ref bt_l2cap_fixed_chan. + * + * @note Fixed L2CAP channels are according to the Core Specification (3.A.2.1 v6.0) reserved + * for the stack, but this allows the application to define their own, for instance if there + * are memory constraints and dynamic channels are not suitable. The application needs to + * make sure that the CID for the fixed channel is not already in use. + * + * @param _name Name of the fixed L2CAP channel. The channels are sorted lexicographically, and + * will be initialized in the same order. + */ +#define BT_L2CAP_FIXED_CHANNEL_DEFINE(_name) \ + static const STRUCT_SECTION_ITERABLE(bt_l2cap_fixed_chan, \ + _CONCAT(bt_l2cap_fixed_chan, _name)) + /** L2CAP Endpoint Link Mode. Basic mode. */ #define BT_L2CAP_BR_LINK_MODE_BASIC 0x00 /** L2CAP Endpoint Link Mode. Retransmission mode. */ @@ -910,23 +993,21 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan); /** @brief Send data to L2CAP channel * - * Send data from buffer to the channel. If credits are not available, buf will - * be queued and sent as and when credits are received from peer. - * Regarding to first input parameter, to get details see reference description - * to bt_l2cap_chan_connect() API above. + * Send data from buffer to the channel. For dynamic channels; if credits are + * not available, buf will be queued and sent as and when credits are received + * from peer. * * Network buffer fragments (ie `buf->frags`) are not supported. * - * When sending L2CAP data over an BR/EDR connection the application is sending - * L2CAP PDUs. The application is required to have reserved - * @ref BT_L2CAP_CHAN_SEND_RESERVE bytes in the buffer before sending. - * The application should use the BT_L2CAP_BUF_SIZE() helper to correctly - * size the buffers for the for the outgoing buffer pool. + * When sending L2CAP data over an BR/EDR connection or a fixed L2CAP channel, + * the application is sending L2CAP PDUs. The application is required to have + * reserved @ref BT_L2CAP_CHAN_SEND_RESERVE bytes in the buffer before sending. + * The application should use the BT_L2CAP_BUF_SIZE() helper to correctly size + * the buffers for the for the outgoing buffer pool. * - * When sending L2CAP data over an LE connection the application is sending - * L2CAP SDUs. The application shall reserve + * When sending L2CAP data over a dynamic L2CAP channel, the application is + * sending L2CAP SDUs. The application shall reserve * @ref BT_L2CAP_SDU_CHAN_SEND_RESERVE bytes in the buffer before sending. - * * The application can use the BT_L2CAP_SDU_BUF_SIZE() helper to correctly size * the buffer to account for the reserved headroom. * @@ -942,9 +1023,13 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan); * @note Buffer ownership is transferred to the stack in case of success, in * case of an error the caller retains the ownership of the buffer. * + * @param chan The channel to send the data to. See @ref bt_l2cap_chan_connect + * for more details. + * @param buf Buffer containing the data. + * * @return 0 in case of success or negative value in case of error. * @return -EINVAL if `buf` or `chan` is NULL. - * @return -EINVAL if `chan` is not either BR/EDR or LE credit-based. + * @return -EINVAL if `chan` is not either BR/EDR or LE based. * @return -EINVAL if buffer doesn't have enough bytes reserved to fit header. * @return -EINVAL if buffer's reference counter != 1 * @return -EMSGSIZE if `buf` is larger than `chan`'s MTU. diff --git a/include/zephyr/bluetooth/mesh/access.h b/include/zephyr/bluetooth/mesh/access.h index 71aa89db0ef3..c2dc4df4fdac 100644 --- a/include/zephyr/bluetooth/mesh/access.h +++ b/include/zephyr/bluetooth/mesh/access.h @@ -12,8 +12,13 @@ #include #include +#include #include +/** + * @cond INTERNAL_HIDDEN + */ + /* Internal macros used to initialize array members */ #define BT_MESH_KEY_UNUSED_ELT_(IDX, _) BT_MESH_KEY_UNUSED #define BT_MESH_ADDR_UNASSIGNED_ELT_(IDX, _) BT_MESH_ADDR_UNASSIGNED @@ -30,6 +35,8 @@ #define BT_MESH_MODEL_UUIDS_UNASSIGNED() #endif +/** @endcond */ + #define BT_MESH_MODEL_RUNTIME_INIT(_user_data) \ .rt = &(struct bt_mesh_model_rt_ctx){ .user_data = (_user_data) }, @@ -171,194 +178,6 @@ struct bt_mesh_elem { const struct bt_mesh_model * const vnd_models; }; -/** - * @name Foundation Models - * @{ - */ -/** Configuration Server */ -#define BT_MESH_MODEL_ID_CFG_SRV 0x0000 -/** Configuration Client */ -#define BT_MESH_MODEL_ID_CFG_CLI 0x0001 -/** Health Server */ -#define BT_MESH_MODEL_ID_HEALTH_SRV 0x0002 -/** Health Client */ -#define BT_MESH_MODEL_ID_HEALTH_CLI 0x0003 -/** Remote Provisioning Server */ -#define BT_MESH_MODEL_ID_REMOTE_PROV_SRV 0x0004 -/** Remote Provisioning Client */ -#define BT_MESH_MODEL_ID_REMOTE_PROV_CLI 0x0005 -/** Bridge Configuration Sever */ -#define BT_MESH_MODEL_ID_BRG_CFG_SRV 0x0008 -/** Bridge Configuration Client */ -#define BT_MESH_MODEL_ID_BRG_CFG_CLI 0x0009 -/** Private Beacon Server */ -#define BT_MESH_MODEL_ID_PRIV_BEACON_SRV 0x000a -/** Private Beacon Client */ -#define BT_MESH_MODEL_ID_PRIV_BEACON_CLI 0x000b -/** SAR Configuration Server */ -#define BT_MESH_MODEL_ID_SAR_CFG_SRV 0x000e -/** SAR Configuration Client */ -#define BT_MESH_MODEL_ID_SAR_CFG_CLI 0x000f -/** Opcodes Aggregator Server */ -#define BT_MESH_MODEL_ID_OP_AGG_SRV 0x0010 -/** Opcodes Aggregator Client */ -#define BT_MESH_MODEL_ID_OP_AGG_CLI 0x0011 -/** Large Composition Data Server */ -#define BT_MESH_MODEL_ID_LARGE_COMP_DATA_SRV 0x0012 -/** Large Composition Data Client */ -#define BT_MESH_MODEL_ID_LARGE_COMP_DATA_CLI 0x0013 -/** Solicitation PDU RPL Configuration Client */ -#define BT_MESH_MODEL_ID_SOL_PDU_RPL_SRV 0x0014 -/** Solicitation PDU RPL Configuration Server */ -#define BT_MESH_MODEL_ID_SOL_PDU_RPL_CLI 0x0015 -/** Private Proxy Server */ -#define BT_MESH_MODEL_ID_ON_DEMAND_PROXY_SRV 0x000c -/** Private Proxy Client */ -#define BT_MESH_MODEL_ID_ON_DEMAND_PROXY_CLI 0x000d -/** - * @} - */ - -/** - * @name Models from the Mesh Model Specification - * @{ - */ -/** Generic OnOff Server */ -#define BT_MESH_MODEL_ID_GEN_ONOFF_SRV 0x1000 -/** Generic OnOff Client */ -#define BT_MESH_MODEL_ID_GEN_ONOFF_CLI 0x1001 -/** Generic Level Server */ -#define BT_MESH_MODEL_ID_GEN_LEVEL_SRV 0x1002 -/** Generic Level Client */ -#define BT_MESH_MODEL_ID_GEN_LEVEL_CLI 0x1003 -/** Generic Default Transition Time Server */ -#define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV 0x1004 -/** Generic Default Transition Time Client */ -#define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI 0x1005 -/** Generic Power OnOff Server */ -#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV 0x1006 -/** Generic Power OnOff Setup Server */ -#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV 0x1007 -/** Generic Power OnOff Client */ -#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI 0x1008 -/** Generic Power Level Server */ -#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV 0x1009 -/** Generic Power Level Setup Server */ -#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV 0x100a -/** Generic Power Level Client */ -#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_CLI 0x100b -/** Generic Battery Server */ -#define BT_MESH_MODEL_ID_GEN_BATTERY_SRV 0x100c -/** Generic Battery Client */ -#define BT_MESH_MODEL_ID_GEN_BATTERY_CLI 0x100d -/** Generic Location Server */ -#define BT_MESH_MODEL_ID_GEN_LOCATION_SRV 0x100e -/** Generic Location Setup Server */ -#define BT_MESH_MODEL_ID_GEN_LOCATION_SETUPSRV 0x100f -/** Generic Location Client */ -#define BT_MESH_MODEL_ID_GEN_LOCATION_CLI 0x1010 -/** Generic Admin Property Server */ -#define BT_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV 0x1011 -/** Generic Manufacturer Property Server */ -#define BT_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV 0x1012 -/** Generic User Property Server */ -#define BT_MESH_MODEL_ID_GEN_USER_PROP_SRV 0x1013 -/** Generic Client Property Server */ -#define BT_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV 0x1014 -/** Generic Property Client */ -#define BT_MESH_MODEL_ID_GEN_PROP_CLI 0x1015 -/** Sensor Server */ -#define BT_MESH_MODEL_ID_SENSOR_SRV 0x1100 -/** Sensor Setup Server */ -#define BT_MESH_MODEL_ID_SENSOR_SETUP_SRV 0x1101 -/** Sensor Client */ -#define BT_MESH_MODEL_ID_SENSOR_CLI 0x1102 -/** Time Server */ -#define BT_MESH_MODEL_ID_TIME_SRV 0x1200 -/** Time Setup Server */ -#define BT_MESH_MODEL_ID_TIME_SETUP_SRV 0x1201 -/** Time Client */ -#define BT_MESH_MODEL_ID_TIME_CLI 0x1202 -/** Scene Server */ -#define BT_MESH_MODEL_ID_SCENE_SRV 0x1203 -/** Scene Setup Server */ -#define BT_MESH_MODEL_ID_SCENE_SETUP_SRV 0x1204 -/** Scene Client */ -#define BT_MESH_MODEL_ID_SCENE_CLI 0x1205 -/** Scheduler Server */ -#define BT_MESH_MODEL_ID_SCHEDULER_SRV 0x1206 -/** Scheduler Setup Server */ -#define BT_MESH_MODEL_ID_SCHEDULER_SETUP_SRV 0x1207 -/** Scheduler Client */ -#define BT_MESH_MODEL_ID_SCHEDULER_CLI 0x1208 -/** Light Lightness Server */ -#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV 0x1300 -/** Light Lightness Setup Server */ -#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV 0x1301 -/** Light Lightness Client */ -#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI 0x1302 -/** Light CTL Server */ -#define BT_MESH_MODEL_ID_LIGHT_CTL_SRV 0x1303 -/** Light CTL Setup Server */ -#define BT_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV 0x1304 -/** Light CTL Client */ -#define BT_MESH_MODEL_ID_LIGHT_CTL_CLI 0x1305 -/** Light CTL Temperature Server */ -#define BT_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV 0x1306 -/** Light HSL Server */ -#define BT_MESH_MODEL_ID_LIGHT_HSL_SRV 0x1307 -/** Light HSL Setup Server */ -#define BT_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV 0x1308 -/** Light HSL Client */ -#define BT_MESH_MODEL_ID_LIGHT_HSL_CLI 0x1309 -/** Light HSL Hue Server */ -#define BT_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV 0x130a -/** Light HSL Saturation Server */ -#define BT_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV 0x130b -/** Light xyL Server */ -#define BT_MESH_MODEL_ID_LIGHT_XYL_SRV 0x130c -/** Light xyL Setup Server */ -#define BT_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV 0x130d -/** Light xyL Client */ -#define BT_MESH_MODEL_ID_LIGHT_XYL_CLI 0x130e -/** Light LC Server */ -#define BT_MESH_MODEL_ID_LIGHT_LC_SRV 0x130f -/** Light LC Setup Server */ -#define BT_MESH_MODEL_ID_LIGHT_LC_SETUPSRV 0x1310 -/** Light LC Client */ -#define BT_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311 -/** - * @} - */ - -/** - * @name Models from the Mesh Binary Large Object Transfer Model Specification - * @{ - */ -/** BLOB Transfer Server */ -#define BT_MESH_MODEL_ID_BLOB_SRV 0x1400 -/** BLOB Transfer Client */ -#define BT_MESH_MODEL_ID_BLOB_CLI 0x1401 -/** - * @} - */ - -/** - * @name Models from the Mesh Device Firmware Update Model Specification - * @{ - */ -/** Firmware Update Server */ -#define BT_MESH_MODEL_ID_DFU_SRV 0x1402 -/** Firmware Update Client */ -#define BT_MESH_MODEL_ID_DFU_CLI 0x1403 -/** Firmware Distribution Server */ -#define BT_MESH_MODEL_ID_DFD_SRV 0x1404 -/** Firmware Distribution Client */ -#define BT_MESH_MODEL_ID_DFD_CLI 0x1405 -/** - * @} - */ - /** Model opcode handler. */ struct bt_mesh_model_op { /** OpCode encoded using the BT_MESH_MODEL_OP_* macros */ @@ -386,8 +205,11 @@ struct bt_mesh_model_op { struct net_buf_simple *buf); }; +/** Macro for encoding a 1-byte opcode (used by Bluetooth SIG defined models). */ #define BT_MESH_MODEL_OP_1(b0) (b0) +/** Macro for encoding a 2-byte opcode (used by Bluetooth SIG defined models). */ #define BT_MESH_MODEL_OP_2(b0, b1) (((b0) << 8) | (b1)) +/** Macro for encoding a 3-byte opcode (vendor-specific message). */ #define BT_MESH_MODEL_OP_3(b0, cid) ((((b0) << 16) | 0xc00000) | (cid)) /** Macro for encoding exact message length for fixed-length messages. */ @@ -780,13 +602,13 @@ struct bt_mesh_model_pub { * BT_MESH_MODELS_METADATA_ENTRY macro. */ struct bt_mesh_models_metadata_entry { - /* Length of the metadata */ + /** Length of the metadata */ const uint16_t len; - /* ID of the metadata */ + /** ID of the metadata */ const uint16_t id; - /* Pointer to raw data */ + /** Pointer to raw data */ const void * const data; }; diff --git a/include/zephyr/bluetooth/mesh/main.h b/include/zephyr/bluetooth/mesh/main.h index dfcd1d0bd7c9..76283aa39c8f 100644 --- a/include/zephyr/bluetooth/mesh/main.h +++ b/include/zephyr/bluetooth/mesh/main.h @@ -173,6 +173,7 @@ struct bt_mesh_prov { */ void (*capabilities)(const struct bt_mesh_dev_capabilities *cap); +#if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY /** @brief Output of a number is requested. * * This callback notifies the application that it should @@ -183,7 +184,21 @@ struct bt_mesh_prov { * * @return Zero on success or negative error code otherwise */ - int (*output_number)(bt_mesh_output_action_t act, uint32_t num); + int (*output_number)(bt_mesh_output_action_t act, uint32_t num) __deprecated; +#else + /** @brief Output of a numeric value is requested. + * + * This callback notifies the application that it should + * output the given numeric value using the given action. + * + * @param act Action for outputting the numeric value. + * @param numeric memory with numeric value in the little endian format to be outputted. + * @param size size of the numeric value in bytes. + * + * @return Zero on success or negative error code otherwise + */ + int (*output_numeric)(bt_mesh_output_action_t act, uint8_t *numeric, size_t size); +#endif /** @brief Output of a string is requested. * @@ -202,7 +217,7 @@ struct bt_mesh_prov { * request input from the user using the given action. The * requested input will either be a string or a number, and * the application needs to consequently call the - * bt_mesh_input_string() or bt_mesh_input_number() functions + * bt_mesh_input_string() or bt_mesh_input_numeric() functions * once the data has been acquired from the user. * * @param act Action for inputting data. @@ -313,7 +328,7 @@ struct bt_mesh_rpr_node; /** @brief Provide provisioning input OOB string. * - * This is intended to be called after the bt_mesh_prov input callback + * This is intended to be called after the @ref bt_mesh_prov::input callback * has been called with BT_MESH_ENTER_STRING as the action. * * @param str String. @@ -322,16 +337,30 @@ struct bt_mesh_rpr_node; */ int bt_mesh_input_string(const char *str); +#if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY /** @brief Provide provisioning input OOB number. * - * This is intended to be called after the bt_mesh_prov input callback - * has been called with BT_MESH_ENTER_NUMBER as the action. + * This is intended to be called after the @ref bt_mesh_prov::input callback + * has been called with @ref BT_MESH_ENTER_NUMBER as the action. * * @param num Number. * * @return Zero on success or (negative) error code otherwise. */ -int bt_mesh_input_number(uint32_t num); +__deprecated int bt_mesh_input_number(uint32_t num); +#endif + +/** @brief Provide provisioning input OOB numeric value. + * + * This is intended to be called after the @ref bt_mesh_prov::input callback + * has been called with @ref BT_MESH_ENTER_NUMBER as the action. + * + * @param numeric Pointer to the numeric value in little endian. + * @param size Size of the numeric value in bytes (this is not OOB size). + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_mesh_input_numeric(uint8_t *numeric, size_t size); /** @brief Provide Device public key. * @@ -347,7 +376,7 @@ int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]); * * Instruct the unprovisioned device to use the specified Input OOB * authentication action. When using @ref BT_MESH_PUSH, @ref BT_MESH_TWIST or - * @ref BT_MESH_ENTER_NUMBER, the @ref bt_mesh_prov::output_number callback is + * @ref BT_MESH_ENTER_NUMBER, the @ref bt_mesh_prov::output_numeric callback is * called with a random number that has to be entered on the unprovisioned * device. * @@ -372,7 +401,7 @@ int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size); * * When using @ref BT_MESH_BLINK, @ref BT_MESH_BEEP, @ref BT_MESH_VIBRATE * or @ref BT_MESH_DISPLAY_NUMBER, and the application has to call - * @ref bt_mesh_input_number with the random number indicated by + * @ref bt_mesh_input_numeric with the random number indicated by * the unprovisioned device. * * When using @ref BT_MESH_DISPLAY_STRING, the application has to call diff --git a/include/zephyr/bluetooth/services/ans.h b/include/zephyr/bluetooth/services/ans.h new file mode 100644 index 000000000000..aec1ea7c2af2 --- /dev/null +++ b/include/zephyr/bluetooth/services/ans.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2025 Sean Kyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_ANS_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_ANS_H_ + +/** + * @brief Alert Notification Service (ANS) + * @defgroup bt_ans Alert Notification Service (ANS) + * + * @since 4.4 + * @version 0.1.0 + * + * @ingroup bluetooth + * @{ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Command not supported error code + */ +#define BT_ANS_ERR_CMD_NOT_SUP 0xa0 + +/** + * @brief ANS max text string size in octets + * + * This is the max string size in octets to be saved in a New Alert. Text longer than the max is + * truncated. + * + * section 3.165 of + * https://btprodspecificationrefs.blob.core.windows.net/gatt-specification-supplement/GATT_Specification_Supplement.pdf + * + */ +#define BT_ANS_MAX_TEXT_STR_SIZE 18 + +/** + * @brief ANS Category ID Enum + * + * Enumeration for whether the category is supported. + */ +enum bt_ans_cat { + BT_ANS_CAT_SIMPLE_ALERT, /**< Simple alerts (general notifications). */ + BT_ANS_CAT_EMAIL, /**< Email messages. */ + BT_ANS_CAT_NEWS, /**< News updates. */ + BT_ANS_CAT_CALL, /**< Incoming call alerts. */ + BT_ANS_CAT_MISSED_CALL, /**< Missed call alerts. */ + BT_ANS_CAT_SMS_MMS, /**< SMS/MMS text messages. */ + BT_ANS_CAT_VOICE_MAIL, /**< Voicemail notifications. */ + BT_ANS_CAT_SCHEDULE, /**< Calendar or schedule alerts. */ + BT_ANS_CAT_HIGH_PRI_ALERT, /**< High-priority alerts. */ + BT_ANS_CAT_INSTANT_MESSAGE, /**< Instant messaging alerts. */ + + /** @cond INTERNAL_HIDDEN */ + BT_ANS_CAT_NUM, /**< Marker for the number of categories. */ + /** @endcond */ + + /* 10–15 reserved for future use */ +}; + +/** + * @brief Set the support for a given new alert category + * + * @param mask The bitmask of supported categories + * + * @return 0 on success + * @return negative error codes on failure + */ +int bt_ans_set_new_alert_support_category(uint16_t mask); + +/** + * @brief Set the support for a given unread new alert category + * + * @param mask The bitmask of supported categories + * + * @return 0 on success + * @return negative error codes on failure + */ +int bt_ans_set_unread_support_category(uint16_t mask); + +/** + * @brief Send a new alert to remote devices + * + * The new alert is transmitted to the remote devices if notifications are enabled. Each category + * will save the latest call to this function in case an immediate replay is requested via the ANS + * control point. + * + * @note This function waits on a Mutex with @ref K_FOREVER to ensure atomic updates to notification + * structs. To avoid deadlocks, do not call this function in BT RX or System Workqueue threads. + * + * @param conn The connection object to send the alert to + * @param category The category the notification is for + * @param num_new Number of new alerts since last alert + * @param text Text brief of alert, null terminated + * + * @return 0 on success + * @return negative error codes on failure + */ +int bt_ans_notify_new_alert(struct bt_conn *conn, enum bt_ans_cat category, uint8_t num_new, + const char *text); + +/** + * @brief Set the total unread count for a given category + * + * The unread count is transmitted to the remote devices if notifications are enabled. Each category + * will save the latest call to this function in case an immediate replay is requested via the ANS + * control point. + * + * @note This function waits on a Mutex with @ref K_FOREVER to ensure atomic updates to notification + * structs. To avoid deadlocks, do not call this function in BT RX or System Workqueue threads. + * + * @param conn The connection object to send the alert to + * @param category The category the unread count is for + * @param unread Total number of unread alerts + * + * @return 0 on success + * @return negative error codes on failure + */ +int bt_ans_set_unread_count(struct bt_conn *conn, enum bt_ans_cat category, uint8_t unread); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_ANS_H_ */ diff --git a/include/zephyr/devicetree/fixed-partitions.h b/include/zephyr/devicetree/fixed-partitions.h index 14bb96bfc592..ff44e07ef644 100644 --- a/include/zephyr/devicetree/fixed-partitions.h +++ b/include/zephyr/devicetree/fixed-partitions.h @@ -131,7 +131,7 @@ extern "C" { * node containing it. */ #define DT_FIXED_PARTITION_ADDR(node_id) \ - (DT_REG_ADDR(DT_MEM_FROM_FIXED_PARTITION(node_id)) + DT_REG_ADDR(node_id)) + (DT_REG_ADDR(node_id) + DT_REG_ADDR(DT_GPARENT(node_id))) /** * @brief Test if fixed-subpartitions compatible node exists @@ -160,7 +160,7 @@ extern "C" { */ #define DT_MTD_FROM_FIXED_SUBPARTITION(node_id) \ COND_CODE_1(DT_NODE_EXISTS(DT_MEM_FROM_FIXED_SUBPARTITION(node_id)), \ - (DT_PARENT(DT_MEM_FROM_FIXED_SUBPARTITION(node_id))), (DT_GPARENT(node_id))) + (DT_PARENT(DT_MEM_FROM_FIXED_SUBPARTITION(node_id))), (DT_GPARENT(DT_PARENT(node_id)))) /** * @brief Get the absolute address of a fixed subpartition @@ -207,7 +207,7 @@ extern "C" { * node containing it. */ #define DT_FIXED_SUBPARTITION_ADDR(node_id) \ - (DT_REG_ADDR(DT_MEM_FROM_FIXED_SUBPARTITION(node_id)) + DT_REG_ADDR(node_id)) + (DT_REG_ADDR(node_id) + DT_REG_ADDR(DT_GPARENT(DT_PARENT(node_id)))) /** * @} diff --git a/include/zephyr/drivers/can/can_mcan.h b/include/zephyr/drivers/can/can_mcan.h index 25eeb437efba..28aa899371c8 100644 --- a/include/zephyr/drivers/can/can_mcan.h +++ b/include/zephyr/drivers/can/can_mcan.h @@ -1065,6 +1065,7 @@ struct can_mcan_data { struct k_mutex lock; struct k_sem tx_sem; struct k_mutex tx_mtx; + struct k_timer txbcf_timer; void *custom; } __aligned(4); diff --git a/include/zephyr/drivers/clock_control/nrf_clock_control.h b/include/zephyr/drivers/clock_control/nrf_clock_control.h index 37fc4a1f1a85..7fa4530a6a04 100644 --- a/include/zephyr/drivers/clock_control/nrf_clock_control.h +++ b/include/zephyr/drivers/clock_control/nrf_clock_control.h @@ -188,6 +188,29 @@ uint32_t z_nrf_clock_bt_ctlr_hf_get_startup_time_us(void); /* Specifies that default precision of the clock is sufficient. */ #define NRF_CLOCK_CONTROL_PRECISION_DEFAULT 0 +/* AUXPLL devicetree takes in raw register values, these are the actual frequencies outputted */ +#define CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_MIN_HZ 80000000 +#define CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_AUDIO_44K1_HZ 11289591 +#define CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_USB24M_HZ 24000000 +#define CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_AUDIO_48K_HZ 12287963 + +/* Internal helper macro to map DT property value to output frequency */ +#define _CLOCK_CONTROL_NRF_AUXPLL_MAP_FREQ(freq_val) \ + ((freq_val) == NRF_AUXPLL_FREQ_DIV_MIN ? \ + CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_MIN_HZ : \ + (freq_val) == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1 ? \ + CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_AUDIO_44K1_HZ : \ + (freq_val) == NRF_AUXPLL_FREQ_DIV_USB24M ? \ + CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_USB24M_HZ : \ + (freq_val) == NRF_AUXPLL_FREQ_DIV_AUDIO_48K ? \ + CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_AUDIO_48K_HZ : 0) + +/* Public macro to get output frequency of AUXPLL */ +#define CLOCK_CONTROL_NRF_AUXPLL_GET_FREQ(node) \ + COND_CODE_1(DT_NODE_HAS_PROP(node, nordic_frequency), \ + (_CLOCK_CONTROL_NRF_AUXPLL_MAP_FREQ(DT_PROP(node, nordic_frequency))), \ + (0)) + struct nrf_clock_spec { uint32_t frequency; uint16_t accuracy : 15; diff --git a/include/zephyr/drivers/comparator/nrf_comp.h b/include/zephyr/drivers/comparator/nrf_comp.h index 59e1cbbb3ce9..09c870f9a33c 100644 --- a/include/zephyr/drivers/comparator/nrf_comp.h +++ b/include/zephyr/drivers/comparator/nrf_comp.h @@ -7,56 +7,13 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_COMP_H_ #define ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_COMP_H_ +#include #include #ifdef __cplusplus extern "C" { #endif -/** Positive input selection */ -enum comp_nrf_comp_psel { - /** AIN0 external input */ - COMP_NRF_COMP_PSEL_AIN0, - /** AIN1 external input */ - COMP_NRF_COMP_PSEL_AIN1, - /** AIN2 external input */ - COMP_NRF_COMP_PSEL_AIN2, - /** AIN3 external input */ - COMP_NRF_COMP_PSEL_AIN3, - /** AIN4 external input */ - COMP_NRF_COMP_PSEL_AIN4, - /** AIN5 external input */ - COMP_NRF_COMP_PSEL_AIN5, - /** AIN6 external input */ - COMP_NRF_COMP_PSEL_AIN6, - /** AIN7 external input */ - COMP_NRF_COMP_PSEL_AIN7, - /** VDD / 2 */ - COMP_NRF_COMP_PSEL_VDD_DIV2, - /** VDDH / 5 */ - COMP_NRF_COMP_PSEL_VDDH_DIV5, -}; - -/** External reference selection */ -enum comp_nrf_comp_extrefsel { - /** AIN0 external input */ - COMP_NRF_COMP_EXTREFSEL_AIN0, - /** AIN1 external input */ - COMP_NRF_COMP_EXTREFSEL_AIN1, - /** AIN2 external input */ - COMP_NRF_COMP_EXTREFSEL_AIN2, - /** AIN3 external input */ - COMP_NRF_COMP_EXTREFSEL_AIN3, - /** AIN4 external input */ - COMP_NRF_COMP_EXTREFSEL_AIN4, - /** AIN5 external input */ - COMP_NRF_COMP_EXTREFSEL_AIN5, - /** AIN6 external input */ - COMP_NRF_COMP_EXTREFSEL_AIN6, - /** AIN7 external input */ - COMP_NRF_COMP_EXTREFSEL_AIN7, -}; - /** Reference selection */ enum comp_nrf_comp_refsel { /** Internal 1.2V reference */ @@ -103,14 +60,14 @@ enum comp_nrf_comp_isource { * @note Hysteresis up in volts = ((th_up + 1) / 64) * ref */ struct comp_nrf_comp_se_config { - /** Positive input selection */ - enum comp_nrf_comp_psel psel; + /** Positive input selection defined by the NRF_COMP_AIN defines */ + uint8_t psel; /** Speed mode selection */ enum comp_nrf_comp_sp_mode sp_mode; /** Current source configuration */ enum comp_nrf_comp_isource isource; - /** External reference selection */ - enum comp_nrf_comp_extrefsel extrefsel; + /** External reference input selection defined by the NRF_COMP_AIN defines */ + uint8_t extrefsel; /** Reference selection */ enum comp_nrf_comp_refsel refsel; /** Hysteresis down threshold configuration */ @@ -133,14 +90,14 @@ int comp_nrf_comp_configure_se(const struct device *dev, /** Differential mode configuration structure */ struct comp_nrf_comp_diff_config { - /** Positive input selection */ - enum comp_nrf_comp_psel psel; + /** Positive input selection defined by the NRF_COMP_AIN defines */ + uint8_t psel; /** Speed mode selection */ enum comp_nrf_comp_sp_mode sp_mode; /** Current source configuration */ enum comp_nrf_comp_isource isource; - /** Negative input selection */ - enum comp_nrf_comp_extrefsel extrefsel; + /** Negative input selection defined by the NRF_COMP_AIN defines */ + uint8_t extrefsel; /** Hysteresis configuration */ bool enable_hyst; }; diff --git a/include/zephyr/drivers/comparator/nrf_lpcomp.h b/include/zephyr/drivers/comparator/nrf_lpcomp.h index e1f2343a8de8..1cae4caae330 100644 --- a/include/zephyr/drivers/comparator/nrf_lpcomp.h +++ b/include/zephyr/drivers/comparator/nrf_lpcomp.h @@ -7,40 +7,13 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_LPCOMP_H_ #define ZEPHYR_INCLUDE_DRIVERS_COMP_NRF_LPCOMP_H_ +#include #include #ifdef __cplusplus extern "C" { #endif -/** Positive input selection */ -enum comp_nrf_lpcomp_psel { - /** AIN0 external input */ - COMP_NRF_LPCOMP_PSEL_AIN0, - /** AIN1 external input */ - COMP_NRF_LPCOMP_PSEL_AIN1, - /** AIN2 external input */ - COMP_NRF_LPCOMP_PSEL_AIN2, - /** AIN3 external input */ - COMP_NRF_LPCOMP_PSEL_AIN3, - /** AIN4 external input */ - COMP_NRF_LPCOMP_PSEL_AIN4, - /** AIN5 external input */ - COMP_NRF_LPCOMP_PSEL_AIN5, - /** AIN6 external input */ - COMP_NRF_LPCOMP_PSEL_AIN6, - /** AIN7 external input */ - COMP_NRF_LPCOMP_PSEL_AIN7, -}; - -/** External reference selection */ -enum comp_nrf_lpcomp_extrefsel { - /** AIN0 external input */ - COMP_NRF_LPCOMP_EXTREFSEL_AIN0, - /** AIN1 external input */ - COMP_NRF_LPCOMP_EXTREFSEL_AIN1, -}; - /** Reference selection */ enum comp_nrf_lpcomp_refsel { /** Use (VDD * (1/8)) as reference */ @@ -83,10 +56,10 @@ enum comp_nrf_lpcomp_refsel { * @note extrefsel is only used if refsel == COMP_NRF_LPCOMP_REFSEL_AREF */ struct comp_nrf_lpcomp_config { - /** Positive input selection */ - enum comp_nrf_lpcomp_psel psel; - /** External reference selection */ - enum comp_nrf_lpcomp_extrefsel extrefsel; + /** Positive input selection defined by the NRF_COMP_AIN defines */ + uint8_t psel; + /** External reference input selection defined by the NRF_COMP_AIN defines */ + uint8_t extrefsel; /** Reference selection */ enum comp_nrf_lpcomp_refsel refsel; /** Hysteresis configuration */ diff --git a/include/zephyr/drivers/misc/coresight/nrf_etr.h b/include/zephyr/drivers/debug/debug_nrf_etr.h similarity index 52% rename from include/zephyr/drivers/misc/coresight/nrf_etr.h rename to include/zephyr/drivers/debug/debug_nrf_etr.h index 062afa3b61aa..04805a7e2d1d 100644 --- a/include/zephyr/drivers/misc/coresight/nrf_etr.h +++ b/include/zephyr/drivers/debug/debug_nrf_etr.h @@ -3,18 +3,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef _ZEPHYR_DRIVERS_MISC_CORESIGHT_NRF_ETR_H_ -#define _ZEPHYR_DRIVERS_MISC_CORESIGHT_NRF_ETR_H_ +#ifndef _ZEPHYR_DRIVERS_DEBUG_CORESIGHT_NRF_ETR_H_ +#define _ZEPHYR_DRIVERS_DEBUG_CORESIGHT_NRF_ETR_H_ #ifdef __cplusplus extern "C" { #endif /** @brief Flush data from the ETR buffer. */ -void nrf_etr_flush(void); +void debug_nrf_etr_flush(void); #ifdef __cplusplus } #endif -#endif /* _ZEPHYR_DRIVERS_MISC_CORESIGHT_NRF_ETR_H_ */ +#endif /* _ZEPHYR_DRIVERS_DEBUG_CORESIGHT_NRF_ETR_H_ */ diff --git a/include/zephyr/drivers/misc/coresight/stmesp.h b/include/zephyr/drivers/debug/stmesp.h similarity index 96% rename from include/zephyr/drivers/misc/coresight/stmesp.h rename to include/zephyr/drivers/debug/stmesp.h index ce0f64b52dde..d4b245857eb3 100644 --- a/include/zephyr/drivers/misc/coresight/stmesp.h +++ b/include/zephyr/drivers/debug/stmesp.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_DRIVERS_MISC_CORESIGHT_STMESP_H_ -#define ZEPHYR_INCLUDE_DRIVERS_MISC_CORESIGHT_STMESP_H_ +#ifndef ZEPHYR_INCLUDE_DRIVERS_DEBUG_CORESIGHT_STMESP_H_ +#define ZEPHYR_INCLUDE_DRIVERS_DEBUG_CORESIGHT_STMESP_H_ #include @@ -190,4 +190,4 @@ static inline int stmesp_get_port(uint32_t idx, STMESP_Type **port) * @} */ -#endif /* ZEPHYR_INCLUDE_DRIVERS_MISC_CORESIGHT_STMESP_H_ */ +#endif /* ZEPHYR_INCLUDE_DRIVERS_DEBUG_CORESIGHT_STMESP_H_ */ diff --git a/include/zephyr/drivers/mspi.h b/include/zephyr/drivers/mspi.h index c486f48a8ddf..b30627efad78 100644 --- a/include/zephyr/drivers/mspi.h +++ b/include/zephyr/drivers/mspi.h @@ -126,6 +126,8 @@ enum mspi_bus_event { MSPI_BUS_RESET = 0, MSPI_BUS_ERROR = 1, MSPI_BUS_XFER_COMPLETE = 2, + /** @brief When a request or xfer has timed out */ + MSPI_BUS_TIMEOUT = 3, MSPI_BUS_EVENT_MAX, }; @@ -139,6 +141,7 @@ enum mspi_bus_event_cb_mask { MSPI_BUS_RESET_CB = BIT(0), MSPI_BUS_ERROR_CB = BIT(1), MSPI_BUS_XFER_COMPLETE_CB = BIT(2), + MSPI_BUS_TIMEOUT_CB = BIT(3), }; /** diff --git a/include/zephyr/dt-bindings/comparator/nrf-comp.h b/include/zephyr/dt-bindings/comparator/nrf-comp.h new file mode 100644 index 000000000000..1a5407554a15 --- /dev/null +++ b/include/zephyr/dt-bindings/comparator/nrf-comp.h @@ -0,0 +1,21 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NRF_COMP_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NRF_COMP_H_ + +#define NRF_COMP_AIN0 0 /** AIN0 external input */ +#define NRF_COMP_AIN1 1 /** AIN1 external input */ +#define NRF_COMP_AIN2 2 /** AIN2 external input */ +#define NRF_COMP_AIN3 3 /** AIN3 external input */ +#define NRF_COMP_AIN4 4 /** AIN4 external input */ +#define NRF_COMP_AIN5 5 /** AIN5 external input */ +#define NRF_COMP_AIN6 6 /** AIN6 external input */ +#define NRF_COMP_AIN7 7 /** AIN7 external input */ +#define NRF_COMP_AIN_VDD_DIV2 8 /** VDD / 2 */ +#define NRF_COMP_AIN_VDDH_DIV5 9 /** VDDH / 5 */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NRF_COMP_H_ */ diff --git a/include/zephyr/dt-bindings/misc/nordic-tddconf.h b/include/zephyr/dt-bindings/misc/nordic-tddconf.h deleted file mode 100644 index 44bc74e491c0..000000000000 --- a/include/zephyr/dt-bindings/misc/nordic-tddconf.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_TDDCONF_H_ -#define ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_TDDCONF_H_ - -#define NRF_TDDCONF_SOURCE_STMMAINCORE BIT(0) -#define NRF_TDDCONF_SOURCE_ETMMAINCORE BIT(1) -#define NRF_TDDCONF_SOURCE_STMHWEVENTS BIT(2) -#define NRF_TDDCONF_SOURCE_STMPPR BIT(3) -#define NRF_TDDCONF_SOURCE_STMFLPR BIT(4) - -#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_TDDCONF_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h index 9de74061e8da..4c7f1d3145dd 100644 --- a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h @@ -172,6 +172,62 @@ #define NRF_FUN_GRTC_CLKOUT_FAST 55U /** GRTC slow clock output */ #define NRF_FUN_GRTC_CLKOUT_32K 56U +/** SDP_MSPI clock pin */ +#define NRF_FUN_SDP_MSPI_SCK 57U +/** SDP_MSPI data pin 0 */ +#define NRF_FUN_SDP_MSPI_DQ0 58U +/** SDP_MSPI data pin 1 */ +#define NRF_FUN_SDP_MSPI_DQ1 59U +/** SDP_MSPI data pin 2 */ +#define NRF_FUN_SDP_MSPI_DQ2 60U +/** SDP_MSPI data pin 3 */ +#define NRF_FUN_SDP_MSPI_DQ3 61U +/** SDP_MSPI data pin 4 */ +#define NRF_FUN_SDP_MSPI_DQ4 62U +/** SDP_MSPI data pin 5 */ +#define NRF_FUN_SDP_MSPI_DQ5 63U +/** SDP_MSPI data pin 6 */ +#define NRF_FUN_SDP_MSPI_DQ6 64U +/** SDP_MSPI data pin 7 */ +#define NRF_FUN_SDP_MSPI_DQ7 65U +/** SDP_MSPI chip select 0 */ +#define NRF_FUN_SDP_MSPI_CS0 66U +/** SDP_MSPI chip select 1 */ +#define NRF_FUN_SDP_MSPI_CS1 67U +/** SDP_MSPI chip select 2 */ +#define NRF_FUN_SDP_MSPI_CS2 68U +/** SDP_MSPI chip select 3 */ +#define NRF_FUN_SDP_MSPI_CS3 69U +/** SDP_MSPI chip select 4 */ +#define NRF_FUN_SDP_MSPI_CS4 70U +/** High-Performance Framework MSPI clock pin */ +#define NRF_FUN_HPF_MSPI_SCK NRF_FUN_SDP_MSPI_SCK +/** High-Performance Framework MSPI data pin 0 */ +#define NRF_FUN_HPF_MSPI_DQ0 NRF_FUN_SDP_MSPI_DQ0 +/** High-Performance Framework MSPI data pin 1 */ +#define NRF_FUN_HPF_MSPI_DQ1 NRF_FUN_SDP_MSPI_DQ1 +/** High-Performance Framework MSPI data pin 2 */ +#define NRF_FUN_HPF_MSPI_DQ2 NRF_FUN_SDP_MSPI_DQ2 +/** High-Performance Framework MSPI data pin 3 */ +#define NRF_FUN_HPF_MSPI_DQ3 NRF_FUN_SDP_MSPI_DQ3 +/** High-Performance Framework MSPI data pin 4 */ +#define NRF_FUN_HPF_MSPI_DQ4 NRF_FUN_SDP_MSPI_DQ4 +/** High-Performance Framework MSPI data pin 5 */ +#define NRF_FUN_HPF_MSPI_DQ5 NRF_FUN_SDP_MSPI_DQ5 +/** High-Performance Framework MSPI data pin 6 */ +#define NRF_FUN_HPF_MSPI_DQ6 NRF_FUN_SDP_MSPI_DQ6 +/** High-Performance Framework MSPI data pin 7 */ +#define NRF_FUN_HPF_MSPI_DQ7 NRF_FUN_SDP_MSPI_DQ7 +/** High-Performance Framework MSPI chip select pin 0 */ +#define NRF_FUN_HPF_MSPI_CS0 NRF_FUN_SDP_MSPI_CS0 +/** High-Performance Framework MSPI chip select pin 1 */ +#define NRF_FUN_HPF_MSPI_CS1 NRF_FUN_SDP_MSPI_CS1 +/** High-Performance Framework MSPI chip select pin 2 */ +#define NRF_FUN_HPF_MSPI_CS2 NRF_FUN_SDP_MSPI_CS2 +/** High-Performance Framework MSPI chip select pin 3 */ +#define NRF_FUN_HPF_MSPI_CS3 NRF_FUN_SDP_MSPI_CS3 +/** High-Performance Framework MSPI chip select pin 4 */ +#define NRF_FUN_HPF_MSPI_CS4 NRF_FUN_SDP_MSPI_CS4 /** TDM SCK in master mode */ #define NRF_FUN_TDM_SCK_M 71U /** TDM SCK in slave mode */ @@ -186,6 +242,18 @@ #define NRF_FUN_TDM_SDOUT 76U /** TDM MCK */ #define NRF_FUN_TDM_MCK 77U +/** SPI master CSN */ +#define NRF_FUN_SPIM_CSN 78U +/** TPIU CLOCK */ +#define NRF_FUN_TPIU_CLOCK 79U +/** TPIU DATA0 */ +#define NRF_FUN_TPIU_DATA0 80U +/** TPIU DATA1 */ +#define NRF_FUN_TPIU_DATA1 81U +/** TPIU DATA2 */ +#define NRF_FUN_TPIU_DATA2 82U +/** TPIU DATA3 */ +#define NRF_FUN_TPIU_DATA3 83U /** @} */ diff --git a/include/zephyr/fs/zms.h b/include/zephyr/fs/zms.h index 41ba053c93c0..cdaa323e3da9 100644 --- a/include/zephyr/fs/zms.h +++ b/include/zephyr/fs/zms.h @@ -77,6 +77,17 @@ struct zms_fs { * @{ */ +/** + * @brief ID type used in the ZMS API. + * + * @note The width of this type depends on @kconfig{CONFIG_ZMS_ID_64BIT}. + */ +#if CONFIG_ZMS_ID_64BIT +typedef uint64_t zms_id_t; +#else +typedef uint32_t zms_id_t; +#endif + /** * @brief Mount a ZMS file system onto the device specified in `fs`. * @@ -128,7 +139,7 @@ int zms_clear(struct zms_fs *fs); * @retval -EINVAL if `fs` is NULL or `len` is invalid. * @retval -ENOSPC if no space is left on the device. */ -ssize_t zms_write(struct zms_fs *fs, uint32_t id, const void *data, size_t len); +ssize_t zms_write(struct zms_fs *fs, zms_id_t id, const void *data, size_t len); /** * @brief Delete an entry from the file system @@ -142,7 +153,7 @@ ssize_t zms_write(struct zms_fs *fs, uint32_t id, const void *data, size_t len); * @retval -EIO if there is a memory read/write error. * @retval -EINVAL if `fs` is NULL. */ -int zms_delete(struct zms_fs *fs, uint32_t id); +int zms_delete(struct zms_fs *fs, zms_id_t id); /** * @brief Read an entry from the file system. @@ -161,7 +172,7 @@ int zms_delete(struct zms_fs *fs, uint32_t id); * @retval -ENOENT if there is no entry with the given `id`. * @retval -EINVAL if `fs` is NULL. */ -ssize_t zms_read(struct zms_fs *fs, uint32_t id, void *data, size_t len); +ssize_t zms_read(struct zms_fs *fs, zms_id_t id, void *data, size_t len); /** * @brief Read a history entry from the file system. @@ -182,7 +193,7 @@ ssize_t zms_read(struct zms_fs *fs, uint32_t id, void *data, size_t len); * @retval -ENOENT if there is no entry with the given `id` and history counter. * @retval -EINVAL if `fs` is NULL. */ -ssize_t zms_read_hist(struct zms_fs *fs, uint32_t id, void *data, size_t len, uint32_t cnt); +ssize_t zms_read_hist(struct zms_fs *fs, zms_id_t id, void *data, size_t len, uint32_t cnt); /** * @brief Gets the length of the data that is stored in an entry with a given `id` @@ -198,7 +209,7 @@ ssize_t zms_read_hist(struct zms_fs *fs, uint32_t id, void *data, size_t len, ui * @retval -ENOENT if there is no entry with the given id. * @retval -EINVAL if `fs` is NULL. */ -ssize_t zms_get_data_length(struct zms_fs *fs, uint32_t id); +ssize_t zms_get_data_length(struct zms_fs *fs, zms_id_t id); /** * @brief Calculate the available free space in the file system. diff --git a/include/zephyr/logging/log_frontend_stmesp.h b/include/zephyr/logging/log_frontend_stmesp.h index 38f33bf62f10..c30972319fa7 100644 --- a/include/zephyr/logging/log_frontend_stmesp.h +++ b/include/zephyr/logging/log_frontend_stmesp.h @@ -9,7 +9,7 @@ #include #include #ifdef CONFIG_LOG_FRONTEND_STMESP -#include +#include #endif #ifdef __cplusplus diff --git a/include/zephyr/modem/at/user_pipe.h b/include/zephyr/modem/at/user_pipe.h new file mode 100644 index 000000000000..9732f5131111 --- /dev/null +++ b/include/zephyr/modem/at/user_pipe.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Embeint Holdings Pty Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_MODEM_AT_USER_PIPE_ +#define ZEPHYR_MODEM_AT_USER_PIPE_ + +#include + +/** + * @brief Initialise the AT command user pipe + * + * @param chat Chat instance that will be used with the user pipe + */ +void modem_at_user_pipe_init(struct modem_chat *chat); + +/** + * @brief Claim the AT command user pipe to run commands + * + * + * @retval 0 On success + * @retval -EPERM Modem is not ready + * @retval -EBUSY User pipe already claimed + */ +int modem_at_user_pipe_claim(void); + +/** + * @brief Release the AT command user pipe to other users + * + * Must be called after @ref modem_at_user_pipe_claim when pipe is no longer + * in use. + */ +void modem_at_user_pipe_release(void); + +#endif /* ZEPHYR_MODEM_AT_USER_PIPE_ */ diff --git a/include/zephyr/modem/backend/uart.h b/include/zephyr/modem/backend/uart.h index 73054b792d8e..6407af8cf6af 100644 --- a/include/zephyr/modem/backend/uart.h +++ b/include/zephyr/modem/backend/uart.h @@ -68,6 +68,7 @@ struct modem_backend_uart_async { struct modem_backend_uart { const struct device *uart; + const struct gpio_dt_spec *dtr_gpio; struct modem_pipe pipe; struct k_work_delayable receive_ready_work; struct k_work transmit_idle_work; @@ -85,6 +86,7 @@ struct modem_backend_uart { struct modem_backend_uart_config { const struct device *uart; + const struct gpio_dt_spec *dtr_gpio; /* Address must be word-aligned when CONFIG_MODEM_BACKEND_UART_ASYNC_HWFC is enabled. */ uint8_t *receive_buf; uint32_t receive_buf_size; diff --git a/include/zephyr/modem/cmux.h b/include/zephyr/modem/cmux.h index 3332c40bd18e..0faa8d5d4b38 100644 --- a/include/zephyr/modem/cmux.h +++ b/include/zephyr/modem/cmux.h @@ -53,14 +53,53 @@ enum modem_cmux_event { typedef void (*modem_cmux_callback)(struct modem_cmux *cmux, enum modem_cmux_event event, void *user_data); +/** + * @brief Contains CMUX instance configuration data + */ +struct modem_cmux_config { + /** Invoked when event occurs */ + modem_cmux_callback callback; + /** Free to use pointer passed to event handler when invoked */ + void *user_data; + /** Receive buffer */ + uint8_t *receive_buf; + /** Size of receive buffer in bytes [127, ...] */ + uint16_t receive_buf_size; + /** Transmit buffer */ + uint8_t *transmit_buf; + /** Size of transmit buffer in bytes [149, ...] */ + uint16_t transmit_buf_size; + /** Enable runtime power management */ + bool enable_runtime_power_management; + /** Close pipe on power save */ + bool close_pipe_on_power_save; + /** Idle timeout for power save */ + k_timeout_t idle_timeout; +}; + /** * @cond INTERNAL_HIDDEN */ +#if CONFIG_MODEM_CMUX_MTU > 127 +#define MODEM_CMUX_HEADER_SIZE 7 +#else +#define MODEM_CMUX_HEADER_SIZE 6 +#endif + + +/* Total size of the CMUX work buffers */ +#define MODEM_CMUX_WORK_BUFFER_SIZE (CONFIG_MODEM_CMUX_MTU + MODEM_CMUX_HEADER_SIZE + \ + CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE_EXTRA) + enum modem_cmux_state { MODEM_CMUX_STATE_DISCONNECTED = 0, MODEM_CMUX_STATE_CONNECTING, MODEM_CMUX_STATE_CONNECTED, + MODEM_CMUX_STATE_ENTER_POWERSAVE, + MODEM_CMUX_STATE_POWERSAVE, + MODEM_CMUX_STATE_CONFIRM_POWERSAVE, + MODEM_CMUX_STATE_WAKEUP, MODEM_CMUX_STATE_DISCONNECTING, }; @@ -74,7 +113,6 @@ enum modem_cmux_receive_state { MODEM_CMUX_RECEIVE_STATE_LENGTH_CONT, MODEM_CMUX_RECEIVE_STATE_DATA, MODEM_CMUX_RECEIVE_STATE_FCS, - MODEM_CMUX_RECEIVE_STATE_DROP, MODEM_CMUX_RECEIVE_STATE_EOF, }; @@ -110,6 +148,10 @@ struct modem_cmux_dlci { #if CONFIG_MODEM_STATS struct modem_stats_buffer receive_buf_stats; #endif + /* Flow control */ + bool flow_control : 1; + bool rx_full : 1; + bool msc_sent : 1; }; struct modem_cmux_frame { @@ -130,30 +172,23 @@ struct modem_cmux { /* Bus pipe */ struct modem_pipe *pipe; - /* Event handler */ - modem_cmux_callback callback; - void *user_data; - /* DLCI channel contexts */ sys_slist_t dlcis; /* State */ enum modem_cmux_state state; - bool flow_control_on; + bool flow_control_on : 1; + bool initiator : 1; /* Work lock */ - bool attached; + bool attached : 1; struct k_spinlock work_lock; /* Receive state*/ enum modem_cmux_receive_state receive_state; - - /* Receive buffer */ - uint8_t *receive_buf; - uint16_t receive_buf_size; uint16_t receive_buf_len; - uint8_t work_buf[CONFIG_MODEM_CMUX_WORK_BUFFER_SIZE]; + uint8_t work_buf[MODEM_CMUX_WORK_BUFFER_SIZE]; /* Transmit buffer */ struct ring_buf transmit_rb; @@ -169,39 +204,25 @@ struct modem_cmux { struct k_work_delayable transmit_work; struct k_work_delayable connect_work; struct k_work_delayable disconnect_work; + struct k_work_delayable runtime_pm_work; /* Synchronize actions */ struct k_event event; + k_timepoint_t t3_timepoint; + k_timepoint_t idle_timepoint; /* Statistics */ #if CONFIG_MODEM_STATS struct modem_stats_buffer receive_buf_stats; struct modem_stats_buffer transmit_buf_stats; #endif + struct modem_cmux_config config; }; /** * @endcond */ -/** - * @brief Contains CMUX instance configuration data - */ -struct modem_cmux_config { - /** Invoked when event occurs */ - modem_cmux_callback callback; - /** Free to use pointer passed to event handler when invoked */ - void *user_data; - /** Receive buffer */ - uint8_t *receive_buf; - /** Size of receive buffer in bytes [127, ...] */ - uint16_t receive_buf_size; - /** Transmit buffer */ - uint8_t *transmit_buf; - /** Size of transmit buffer in bytes [149, ...] */ - uint16_t transmit_buf_size; -}; - /** * @brief Initialize CMUX instance * @param cmux CMUX instance diff --git a/include/zephyr/modem/ppp.h b/include/zephyr/modem/ppp.h index 2b91e51a35c9..69b35897e2d2 100644 --- a/include/zephyr/modem/ppp.h +++ b/include/zephyr/modem/ppp.h @@ -50,27 +50,10 @@ enum modem_ppp_receive_state { }; enum modem_ppp_transmit_state { - /* Idle */ MODEM_PPP_TRANSMIT_STATE_IDLE = 0, - /* Writing header */ MODEM_PPP_TRANSMIT_STATE_SOF, - MODEM_PPP_TRANSMIT_STATE_HDR_FF, - MODEM_PPP_TRANSMIT_STATE_HDR_7D, - MODEM_PPP_TRANSMIT_STATE_HDR_23, - /* Writing protocol */ - MODEM_PPP_TRANSMIT_STATE_PROTOCOL_HIGH, - MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_HIGH, - MODEM_PPP_TRANSMIT_STATE_PROTOCOL_LOW, - MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_LOW, - /* Writing data */ + MODEM_PPP_TRANSMIT_STATE_PROTOCOL, MODEM_PPP_TRANSMIT_STATE_DATA, - MODEM_PPP_TRANSMIT_STATE_ESCAPING_DATA, - /* Writing FCS */ - MODEM_PPP_TRANSMIT_STATE_FCS_LOW, - MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_LOW, - MODEM_PPP_TRANSMIT_STATE_FCS_HIGH, - MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_HIGH, - /* Writing end of frame */ MODEM_PPP_TRANSMIT_STATE_EOF, }; @@ -100,8 +83,6 @@ struct modem_ppp { /* Packet being sent */ enum modem_ppp_transmit_state transmit_state; struct net_pkt *tx_pkt; - uint8_t tx_pkt_escaped; - uint16_t tx_pkt_protocol; uint16_t tx_pkt_fcs; /* Ring buffer used for transmitting partial PPP frame */ @@ -123,6 +104,10 @@ struct modem_ppp { #endif }; +struct modem_ppp_config { + const struct device *dev; +}; + /** * @endcond */ @@ -172,13 +157,17 @@ int modem_ppp_init_internal(const struct device *dev); * network device instance, and binds the modem_ppp instance to the PPP L2 * instance. * + * If underlying cellular device is given, the PPP interface will manage the + * power state of the cellular device when starting and stopping the PPP. + * + * @param _dev Cellular device instance for power management or NULL if not used * @param _name Name of the statically defined modem_ppp instance * @param _init_iface Hook for the PPP L2 network interface init function * @param _prio Initialization priority of the PPP L2 net iface * @param _mtu Max size of net_pkt data sent and received on PPP L2 net iface * @param _buf_size Size of partial PPP frame transmit and receive buffers */ -#define MODEM_PPP_DEFINE(_name, _init_iface, _prio, _mtu, _buf_size) \ +#define MODEM_DEV_PPP_DEFINE(_dev, _name, _init_iface, _prio, _mtu, _buf_size) \ extern const struct ppp_api modem_ppp_ppp_api; \ \ static uint8_t _CONCAT(_name, _receive_buf)[_buf_size]; \ @@ -189,11 +178,30 @@ int modem_ppp_init_internal(const struct device *dev); .receive_buf = _CONCAT(_name, _receive_buf), \ .transmit_buf = _CONCAT(_name, _transmit_buf), \ .buf_size = _buf_size, \ + }; \ + static const struct modem_ppp_config _CONCAT(_name, _config) = { \ + .dev = _dev, \ }; \ \ - NET_DEVICE_INIT(_CONCAT(ppp_net_dev_, _name), "modem_ppp_" # _name, \ - modem_ppp_init_internal, NULL, &_name, NULL, _prio, &modem_ppp_ppp_api, \ - PPP_L2, NET_L2_GET_CTX_TYPE(PPP_L2), _mtu) + NET_DEVICE_INIT(_CONCAT(ppp_net_dev_, _name), "modem_ppp_" #_name, \ + modem_ppp_init_internal, NULL, &_name, &_CONCAT(_name, _config), _prio, \ + &modem_ppp_ppp_api, PPP_L2, NET_L2_GET_CTX_TYPE(PPP_L2), _mtu) + +/** + * @brief Define a modem PPP module for cellular device tree instance. + * + * @see MODEM_DEV_PPP_DEFINE + */ +#define MODEM_DT_INST_PPP_DEFINE(inst, _name, _init_iface, _prio, _mtu, _buf_size) \ + MODEM_DEV_PPP_DEFINE(DEVICE_DT_INST_GET(inst), _name, _init_iface, _prio, _mtu, _buf_size) + +/** + * @brief Define a modem PPP module without a device and bind it to a network interface. + * + * @see MODEM_DEV_PPP_DEFINE + */ +#define MODEM_PPP_DEFINE(_name, _init_iface, _prio, _mtu, _buf_size) \ + MODEM_DEV_PPP_DEFINE(NULL, _name, _init_iface, _prio, _mtu, _buf_size) /** * @} diff --git a/include/zephyr/net/mqtt.h b/include/zephyr/net/mqtt.h index b992714afd32..797f8f339d7f 100644 --- a/include/zephyr/net/mqtt.h +++ b/include/zephyr/net/mqtt.h @@ -763,6 +763,9 @@ struct mqtt_sec_config { uint32_t alpn_protocol_name_count; #endif + /** Indicates the preference for enabling TLS session caching. */ + int session_cache; + /** Peer hostname for ceritificate verification. * May be NULL to skip hostname verification. */ @@ -770,6 +773,9 @@ struct mqtt_sec_config { /** Indicates the preference for copying certificates to the heap. */ int cert_nocopy; + + /** Set socket to native TLS */ + bool set_native_tls; }; /** @brief MQTT transport type. */ diff --git a/include/zephyr/net/socket.h b/include/zephyr/net/socket.h index 2eab2d964628..d5447b097e57 100644 --- a/include/zephyr/net/socket.h +++ b/include/zephyr/net/socket.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #ifdef __cplusplus diff --git a/include/zephyr/net/socket_ncs.h b/include/zephyr/net/socket_ncs.h new file mode 100644 index 000000000000..6a77d6c41f13 --- /dev/null +++ b/include/zephyr/net/socket_ncs.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ +#define ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ + +/** + * @file + * @brief NCS specific additions to the BSD sockets API definitions + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* When CONFIG_NET_SOCKETS_OFFLOAD is enabled, offloaded sockets take precedence + * when creating a new socket. Combine this flag with a socket type when + * creating a socket, to enforce native socket creation (e. g. SOCK_STREAM | SOCK_NATIVE). + * If it's desired to create a native TLS socket, but still offload the + * underlying TCP/UDP socket, use e. g. SOCK_STREAM | SOCK_NATIVE_TLS. + */ +#define SOCK_NATIVE 0x80000000 +#define SOCK_NATIVE_TLS 0x40000000 + +/** Define a base for NCS specific socket options to prevent overlaps with Zephyr's socket options. + */ +#define NET_SOCKET_NCS_BASE 1000 + +/* NCS specific TLS level socket options */ + +/** Socket option to set DTLS handshake timeout, specifically for nRF sockets. + * The option accepts an integer, indicating the total handshake timeout, + * including retransmissions, in seconds. + * Accepted values for the option are: 1, 3, 7, 15, 31, 63, 123. + */ +#define TLS_DTLS_HANDSHAKE_TIMEO (NET_SOCKET_NCS_BASE + 18) + +/** Socket option to save DTLS connection, specifically for nRF sockets. + */ +#define TLS_DTLS_CONN_SAVE (NET_SOCKET_NCS_BASE + 19) + +/** Socket option to load DTLS connection, specifically for nRF sockets. + */ +#define TLS_DTLS_CONN_LOAD (NET_SOCKET_NCS_BASE + 20) + +/** Socket option to get result of latest TLS/DTLS completed handshakes end status, + * specifically for nRF sockets. + * The option accepts an integer, indicating the setting. + * Accepted vaules for the option are: 0 and 1. + */ +#define TLS_DTLS_HANDSHAKE_STATUS (NET_SOCKET_NCS_BASE + 21) + +/* Valid values for TLS_DTLS_HANDSHAKE_TIMEO option */ +#define TLS_DTLS_HANDSHAKE_TIMEO_NONE 0 /**< No timeout */ +#define TLS_DTLS_HANDSHAKE_TIMEO_1S 1 /**< 1 second */ +#define TLS_DTLS_HANDSHAKE_TIMEO_3S 3 /**< 1s + 2s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_7S 7 /**< 1s + 2s + 4s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_15S 15 /**< 1s + 2s + 4s + 8s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_31S 31 /**< 1s + 2s + 4s + 8s + 16s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_63S 63 /**< 1s + 2s + 4s + 8s + 16s + 32s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_123S 123 /**< 1s + 2s + 4s + 8s + 16s + 32s + 60s */ + +/* Valid values for TLS_DTLS_HANDSHAKE_STATUS option */ +#define TLS_DTLS_HANDSHAKE_STATUS_FULL 0 +#define TLS_DTLS_HANDSHAKE_STATUS_CACHED 1 + +/* NCS specific socket options */ + +/** sockopt: enable sending data as part of exceptional events */ +#define SO_EXCEPTIONAL_DATA (NET_SOCKET_NCS_BASE + 33) +/** sockopt: Keep socket open when its PDN connection is lost + * or the device is put into flight mode. + */ +#define SO_KEEPOPEN (NET_SOCKET_NCS_BASE + 34) +/** sockopt: bind to PDN */ +#define SO_BINDTOPDN (NET_SOCKET_NCS_BASE + 40) + +/** sockopt: Release assistance indication (RAI). + * The option accepts an integer, indicating the type of RAI. + * Accepted values for the option are: @ref RAI_NO_DATA, @ref RAI_LAST, @ref RAI_ONE_RESP, + * @ref RAI_ONGOING, @ref RAI_WAIT_MORE. + */ +#define SO_RAI (NET_SOCKET_NCS_BASE + 61) + +/** Release assistance indication (RAI). + * Indicate that the application does not intend to send more data. + * This applies immediately and lets the modem exit connected mode more + * quickly. + * + * @note This requires the socket to be connected. + */ +#define RAI_NO_DATA 1 +/** Release assistance indication (RAI). + * Indicate that the application does not intend to send more data + * after the next call to send() or sendto(). + * This lets the modem exit connected mode more quickly after sending the data. + */ +#define RAI_LAST 2 +/** Release assistance indication (RAI). + * Indicate that the application is expecting to receive just one data packet + * after the next call to send() or sendto(). + * This lets the modem exit connected mode more quickly after having received the data. + */ +#define RAI_ONE_RESP 3 +/** Release assistance indication (RAI). + * Indicate that the socket is in active use by a client application. + * This lets the modem stay in connected mode longer. + */ +#define RAI_ONGOING 4 +/** Release assistance indication (RAI). + * Indicate that the socket is in active use by a server application. + * This lets the modem stay in connected mode longer. + */ +#define RAI_WAIT_MORE 5 + +/** sockopt: set a callback to be called when a send request is acknowledged by the network and + * the data has been acknowledged by the peer, if required by the network protocol, or until the + * timeout, given by the SO_SNDTIMEO socket option, is reached. Valid timeout values are + * 1 to 600 seconds. + * This option takes a @ref socket_ncs_sendcb structure. + * + * @note The callback is executed in an interrupt context. + * Take care to offload any processing as appropriate. + * + * @note This is only supported by the following modem firmware: + * - mfw_nrf9151-ntn + * + * This socket option cannot be used along with the @ref MSG_WAITACK send flag. + */ +#define SO_SENDCB (NET_SOCKET_NCS_BASE + 63) + +/** Parameters returned in the @ref socket_ncs_sendcb_t callback. */ +struct socket_ncs_sendcb_params { + /** Socket handle. */ + int fd; + /** Status. Can be 0 on successful send or EAGAIN on timeout. */ + int status; + /** Number of bytes that was sent. */ + size_t bytes_sent; +}; + +/** Callback type in the @ref socket_ncs_sendcb structure. */ +typedef void (*socket_ncs_sendcb_t)(const struct socket_ncs_sendcb_params *params); + +/** Option value for the @ref SO_SENDCB socket option. */ +struct socket_ncs_sendcb { + /** Callback function. */ + socket_ncs_sendcb_t callback; +}; + +/* NCS specific IPPROTO_ALL level socket options */ + +/** IPv4 and IPv6 protocol level (pseudo-val) for nRF sockets. */ +#define IPPROTO_ALL 512 +/** sockopt: disable all replies to unexpected traffics */ +#define SO_SILENCE_ALL (NET_SOCKET_NCS_BASE + 30) + +/* NCS specific IPPROTO_IP level socket options */ + +/** sockopt: enable IPv4 ICMP replies */ +#define SO_IP_ECHO_REPLY (NET_SOCKET_NCS_BASE + 31) + +/* NCS specific IPPROTO_IPV6 level socket options */ + +/** sockopt: enable IPv6 ICMP replies */ +#define SO_IPV6_ECHO_REPLY (NET_SOCKET_NCS_BASE + 32) + +/** sockopt: Delay IPv6 address refresh during power saving mode */ +#define SO_IPV6_DELAYED_ADDR_REFRESH (NET_SOCKET_NCS_BASE + 62) + +/* NCS specific TCP level socket options */ + +/** sockopt: Configurable TCP server session timeout in minutes. + * Range is 0 to 135. 0 is no timeout and 135 is 2 h 15 min. Default is 0 (no timeout). + */ +#define SO_TCP_SRV_SESSTIMEO (NET_SOCKET_NCS_BASE + 55) + +/* NCS specific gettaddrinfo() flags */ + +/** Assume `service` contains a Packet Data Network (PDN) ID. + * When specified together with the AI_NUMERICSERV flag, + * `service` shall be formatted as follows: "port:pdn_id" + * where "port" is the port number and "pdn_id" is the PDN ID. + * Example: "8080:1", port 8080 PDN ID 1. + * Example: "42:0", port 42 PDN ID 0. + */ +#define AI_PDNSERV 0x1000 + +/* NCS specific send() and sendto() flags */ + +/** Request a blocking send operation until the request is acknowledged. + * When used in send() or sendto(), the request will not return until the + * send operation is completed by lower layers, or until the timeout, given by the SO_SNDTIMEO + * socket option, is reached. Valid timeout values are 1 to 600 seconds. + */ +#define MSG_WAITACK 0x200 + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ */ diff --git a/include/zephyr/platform/hooks.h b/include/zephyr/platform/hooks.h index 9989f640d65e..12defd10ab84 100644 --- a/include/zephyr/platform/hooks.h +++ b/include/zephyr/platform/hooks.h @@ -19,6 +19,19 @@ * directly from application code but may be freely used within the OS. */ +#ifdef CONFIG_SOC_EARLY_RESET_HOOK +/** + * @brief SoC hook executed before data RAM initialization, at the beginning + * of the reset vector. + * + * This hook is implemented by the SoC and can be used to perform any + * SoC-specific initialization. Refer to :kconfig:option:`SOC_EARLY_RESET_HOOK` + * and relevant architecture zephyr-rtos startup implementation for more details. + */ +void soc_early_reset_hook(void); +#else +#define soc_early_reset_hook() do { } while (0) +#endif /** * @brief SoC hook executed at the beginning of the reset vector. diff --git a/include/zephyr/storage/flash_map.h b/include/zephyr/storage/flash_map.h index d8ba414abd3d..9dc6bd91438f 100644 --- a/include/zephyr/storage/flash_map.h +++ b/include/zephyr/storage/flash_map.h @@ -348,15 +348,22 @@ const char *flash_area_label(const struct flash_area *fa); */ uint8_t flash_area_erased_val(const struct flash_area *fa); +#if USE_PARTITION_MANAGER +#include +#else + /** - * Returns non-0 value if fixed-partition of given DTS node label exists. + * Returns non-0 value if fixed-partition or fixed-subpartition of given + * DTS node label exists. * * @param label DTS node label * * @return non-0 if fixed-partition node exists and is enabled; * 0 if node does not exist, is not enabled or is not fixed-partition. */ -#define FIXED_PARTITION_EXISTS(label) DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(label)) +#define FIXED_PARTITION_EXISTS(label) \ + UTIL_OR(DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(label)), \ + DT_FIXED_SUBPARTITION_EXISTS(DT_NODELABEL(label))) /** * Get flash area ID from fixed-partition DTS node label @@ -368,7 +375,7 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); #define FIXED_PARTITION_ID(label) DT_FIXED_PARTITION_ID(DT_NODELABEL(label)) /** - * Get fixed-partition offset from DTS node label + * Get fixed-partition or fixed-subpartition offset from DTS node label * * @param label DTS node label of a partition * @@ -376,6 +383,30 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); */ #define FIXED_PARTITION_OFFSET(label) DT_REG_ADDR(DT_NODELABEL(label)) +/** + * Get fixed-partition or fixed-subpartition address from DTS node label + * + * @param label DTS node label of a partition or subpartition + * + * @return fixed-partition address, as defined for the partition in DTS. + */ +#define FIXED_PARTITION_ADDRESS(label) \ + (COND_CODE_1(DT_FIXED_SUBPARTITION_EXISTS(DT_NODELABEL(label)), \ + (DT_FIXED_SUBPARTITION_ADDR(DT_NODELABEL(label))), \ + (DT_FIXED_PARTITION_ADDR(DT_NODELABEL(label))))) + +/** + * Get fixed-partition or fixed-subpartition address from DTS node + * + * @param node DTS node of a partition + * + * @return fixed-partition address, as defined for the partition in DTS. + */ +#define FIXED_PARTITION_NODE_ADDRESS(node) \ + (COND_CODE_1(DT_FIXED_SUBPARTITION_EXISTS(node), \ + (DT_FIXED_SUBPARTITION_ADDR(node)), \ + (DT_FIXED_PARTITION_ADDR(node)))) + /** * Get fixed-partition offset from DTS node * @@ -421,8 +452,10 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); * @return Pointer to a device. */ #define FIXED_PARTITION_DEVICE(label) \ - DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(label))) - + DEVICE_DT_GET(COND_CODE_1( \ + DT_FIXED_SUBPARTITION_EXISTS(DT_NODELABEL(label)), \ + (DT_MTD_FROM_FIXED_SUBPARTITION(DT_NODELABEL(label))), \ + (DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(label))))) /** * Get device pointer for device the area/partition resides on * @@ -431,7 +464,10 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); * @return Pointer to a device. */ #define FIXED_PARTITION_NODE_DEVICE(node) \ - DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(node)) + DEVICE_DT_GET(COND_CODE_1( \ + DT_FIXED_SUBPARTITION_EXISTS(node), \ + (DT_MTD_FROM_FIXED_SUBPARTITION(node)), \ + (DT_MTD_FROM_FIXED_PARTITION(node)))) /** * Get pointer to flash_area object by partition label @@ -467,8 +503,26 @@ DT_FOREACH_STATUS_OKAY(fixed_partitions, FOR_EACH_PARTITION_TABLE) #undef DECLARE_PARTITION #undef DECLARE_PARTITION_0 #undef FOR_EACH_PARTITION_TABLE + +#define FIXED_SUBPARTITION_1(node) FIXED_SUBPARTITION_0(DT_DEP_ORD(node)) +#define FIXED_SUBPARTITION_0(ord) \ + ((const struct flash_area *)&DT_CAT(global_fixed_subpartition_ORD_, ord)) + +#define DECLARE_SUBPARTITION(node) DECLARE_SUBPARTITION_0(DT_DEP_ORD(node)) +#define DECLARE_SUBPARTITION_0(ord) \ + extern const struct flash_area DT_CAT(global_fixed_subpartition_ORD_, ord); +#define FOR_EACH_SUBPARTITION_TABLE(table) DT_FOREACH_CHILD(table, DECLARE_SUBPARTITION) + +/* Generate declarations */ +DT_FOREACH_STATUS_OKAY(fixed_subpartitions, FOR_EACH_SUBPARTITION_TABLE) + +#undef DECLARE_SUBPARTITION +#undef DECLARE_SUBPARTITION_0 +#undef FOR_EACH_SUBPARTITION_TABLE /** @endcond */ +#endif /* USE_PARTITION_MANAGER */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/usb/class/usbd_hid.h b/include/zephyr/usb/class/usbd_hid.h index 5539369d5b05..79b52dd8fd9d 100644 --- a/include/zephyr/usb/class/usbd_hid.h +++ b/include/zephyr/usb/class/usbd_hid.h @@ -212,6 +212,38 @@ int hid_device_register(const struct device *dev, int hid_device_submit_report(const struct device *dev, const uint16_t size, const uint8_t *const report); +/** + * @brief Set input report polling period + * + * Similar to devicetree property in-polling-period-us, but it allows setting + * different polling periods at runtime. + * + * @kconfig_dep{CONFIG_USBD_HID_SET_POLLING_PERIOD} + * + * @param[in] dev Pointer to HID device + * @param[in] period_us Polling period in microseconds + * + * @return 0 on success, negative errno code on failure. + * @retval -ENOTSUP If API is not enabled. + */ +int hid_device_set_in_polling(const struct device *dev, const unsigned int period_us); + +/** + * @brief Set output report polling period + * + * Similar to devicetree property out-polling-period-us, but it allows setting + * different polling periods at runtime. + * + * @kconfig_dep{CONFIG_USBD_HID_SET_POLLING_PERIOD} + * + * @param[in] dev Pointer to HID device + * @param[in] period_us Polling period in microseconds + * + * @return 0 on success, negative errno code on failure. + * @retval -ENOTSUP If API is not enabled. + */ +int hid_device_set_out_polling(const struct device *dev, const unsigned int period_us); + /** * @} */ diff --git a/kernel/Kconfig b/kernel/Kconfig index bb2c5bade905..d46026508ae6 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -457,6 +457,7 @@ config SKIP_BSS_CLEAR config BOOT_BANNER bool "Boot banner" default y + depends on !NCS_BOOT_BANNER select PRINTK select EARLY_CONSOLE help @@ -734,6 +735,7 @@ config NUM_MBOX_ASYNC_MSGS config EVENTS bool "Event objects" + depends on MULTITHREADING help This option enables event objects. Threads may wait on event objects for specific events, but both threads and ISRs may deliver diff --git a/kernel/Kconfig.init b/kernel/Kconfig.init index 495381638fb0..c752fa5a0e43 100644 --- a/kernel/Kconfig.init +++ b/kernel/Kconfig.init @@ -6,6 +6,28 @@ menu "SoC and Board Hooks" +config SOC_EARLY_RESET_HOOK + bool "Run SoC-specific early reset hook" + help + Run a SoC-specific hook early in the reset/startup code (__start). + A custom hook soc_early_reset_hook() will be executed at the beginning + of the architecture-specific startup code, after hardware has been + configured (as required by CONFIG_INIT_ARCH_HW_AT_BOOT) but before + architecture's own resume logic. + + Returning from this hook is not mandatory: it can be used to implement + special logic to resume execution in some scenarios (for example, when + a bootloader is used). + + The stack pointer register should be considered as not initialized upon + call to this hook. In particular, this means that the hook is NOT allowed + to "push" any data using this stack pointer value. However, the hook may + use an implementation-specific area as stack if desired; in such case, + the original value of the stack pointer needs not to be "restored" before + returning control to the hook's caller. + + Additional constraints may be imposed on the hook by the architecture. + config SOC_RESET_HOOK bool "Run early SoC reset hook" help diff --git a/kernel/banner.c b/kernel/banner.c index 5cadda0a5e98..a16784cb975c 100644 --- a/kernel/banner.c +++ b/kernel/banner.c @@ -24,7 +24,7 @@ #endif /* BUILD_VERSION */ #endif /* !BANNER_VERSION */ -void boot_banner(void) +__weak void boot_banner(void) { #if defined(CONFIG_BOOT_DELAY) && (CONFIG_BOOT_DELAY > 0) #ifdef CONFIG_BOOT_BANNER diff --git a/lib/heap/Kconfig b/lib/heap/Kconfig index 0d97da3e340b..9a39ab8ad73b 100644 --- a/lib/heap/Kconfig +++ b/lib/heap/Kconfig @@ -81,7 +81,7 @@ config HEAP_LISTENER choice prompt "Supported heap sizes" depends on !64BIT - default SYS_HEAP_SMALL_ONLY if (SRAM_SIZE <= 256) + default SYS_HEAP_SMALL_ONLY if (SRAM_SIZE <= 256) && !PARTITION_MANAGER_ENABLED default SYS_HEAP_AUTO help Heaps using reduced-size chunk headers can accommodate so called diff --git a/lib/libc/common/source/stdlib/malloc.c b/lib/libc/common/source/stdlib/malloc.c index 2b01e152f009..2821ae8173ac 100644 --- a/lib/libc/common/source/stdlib/malloc.c +++ b/lib/libc/common/source/stdlib/malloc.c @@ -25,6 +25,20 @@ #include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); +#if USE_PARTITION_MANAGER + +#include + +#define RAM_SIZE PM_SRAM_SIZE +#define RAM_ADDR PM_SRAM_ADDRESS + +#else /* ! USE_PARTITION_MANAGER */ + +#define RAM_SIZE (KB((size_t) CONFIG_SRAM_SIZE)) +#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS + +#endif /* USE_PARTITION_MANAGER */ + #ifdef CONFIG_COMMON_LIBC_MALLOC #if (CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE != 0) @@ -106,8 +120,8 @@ static POOL_SECTION unsigned char __aligned(HEAP_ALIGN) malloc_arena[HEAP_SIZE]; extern char _heap_sentry[]; # define HEAP_SIZE ROUND_DOWN((POINTER_TO_UINT(_heap_sentry) - HEAP_BASE), HEAP_ALIGN) # else -# define HEAP_SIZE ROUND_DOWN((KB((size_t) CONFIG_SRAM_SIZE) - \ - ((size_t) HEAP_BASE - (size_t) CONFIG_SRAM_BASE_ADDRESS)), HEAP_ALIGN) +# define HEAP_SIZE ROUND_DOWN((RAM_SIZE - \ + ((size_t) HEAP_BASE - (size_t) RAM_ADDR)), HEAP_ALIGN) # endif /* else CONFIG_XTENSA */ # endif /* else CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE > 0 */ diff --git a/lib/os/clock.c b/lib/os/clock.c index 0d5813f49fef..2b9968b2eeb4 100644 --- a/lib/os/clock.c +++ b/lib/os/clock.c @@ -158,7 +158,7 @@ int z_impl_sys_clock_nanosleep(int clock_id, int flags, const struct timespec *r { k_timepoint_t end; k_timeout_t timeout; - struct timespec duration; + struct timespec duration = {0, 0}; const bool update_rmtp = rmtp != NULL; const bool abstime = (flags & SYS_TIMER_ABSTIME) != 0; diff --git a/lib/os/zvfs/Kconfig b/lib/os/zvfs/Kconfig index a9c9518a1d5d..495d5c849685 100644 --- a/lib/os/zvfs/Kconfig +++ b/lib/os/zvfs/Kconfig @@ -6,7 +6,6 @@ menuconfig ZVFS bool "Zephyr virtual filesystem (ZVFS) support [EXPERIMENTAL]" select FDTABLE - select EXPERIMENTAL help ZVFS is a central, Zephyr-native library that provides a common interoperable API for all types of file descriptors such as those from the non-virtual FS, sockets, eventfds, FILE *'s diff --git a/modules/hal_nordic/CMakeLists.txt b/modules/hal_nordic/CMakeLists.txt index b6f352864123..e5b1ab60dfca 100644 --- a/modules/hal_nordic/CMakeLists.txt +++ b/modules/hal_nordic/CMakeLists.txt @@ -13,6 +13,7 @@ if(CONFIG_NRF_REGTOOL_GENERATE_UICR) endif() if(DEFINED nrf_regtool_components) find_package(nrf-regtool 9.2.0 + REQUIRED COMPONENTS ${nrf_regtool_components} PATHS ${CMAKE_CURRENT_LIST_DIR}/nrf-regtool NO_CMAKE_PATH diff --git a/modules/hal_nordic/Kconfig b/modules/hal_nordic/Kconfig index b8b659374752..7be30750627d 100644 --- a/modules/hal_nordic/Kconfig +++ b/modules/hal_nordic/Kconfig @@ -203,6 +203,20 @@ config NRF_802154_PENDING_EXTENDED_ADDRESSES config NRF_802154_ENCRYPTION bool "nRF 802.15.4 AES-CCM* authentication & encryption" depends on !CRYPTO_NRF_ECB + select NRF_802154_IE_WRITER + select NRF_802154_SECURITY_WRITER + help + Enable module for encryption and authentication of outgoing frames and Acks. + +config NRF_802154_IE_WRITER + bool "Information element writer" + help + Enable data injection for some Information Element types. + +config NRF_802154_SECURITY_WRITER + bool "Security frame counter writer" + help + Enable injection of security frame counter. config NRF_802154_SECURITY_KEY_STORAGE_SIZE int "nRF 802.15.4 security key storage size" diff --git a/modules/hal_nordic/nrf_802154/CMakeLists.txt b/modules/hal_nordic/nrf_802154/CMakeLists.txt index 957019ff1e67..1f504242cb22 100644 --- a/modules/hal_nordic/nrf_802154/CMakeLists.txt +++ b/modules/hal_nordic/nrf_802154/CMakeLists.txt @@ -70,12 +70,20 @@ endif() if (CONFIG_NRF_802154_ENCRYPTION) target_compile_definitions(zephyr-802154-interface INTERFACE NRF_802154_ENCRYPTION_ENABLED=1) - target_compile_definitions(zephyr-802154-interface INTERFACE NRF_802154_SECURITY_WRITER_ENABLED=1) - target_compile_definitions(zephyr-802154-interface INTERFACE NRF_802154_IE_WRITER_ENABLED=1) else () target_compile_definitions(zephyr-802154-interface INTERFACE NRF_802154_ENCRYPTION_ENABLED=0) - target_compile_definitions(zephyr-802154-interface INTERFACE NRF_802154_SECURITY_WRITER_ENABLED=0) +endif () + +if (CONFIG_NRF_802154_IE_WRITER) + target_compile_definitions(zephyr-802154-interface INTERFACE NRF_802154_IE_WRITER_ENABLED=1) +else () target_compile_definitions(zephyr-802154-interface INTERFACE NRF_802154_IE_WRITER_ENABLED=0) +endif () + +if (CONFIG_NRF_802154_SECURITY_WRITER) + target_compile_definitions(zephyr-802154-interface INTERFACE NRF_802154_SECURITY_WRITER_ENABLED=1) +else () + target_compile_definitions(zephyr-802154-interface INTERFACE NRF_802154_SECURITY_WRITER_ENABLED=0) endif() if (NOT CONFIG_IEEE802154_NRF5 AND NOT CONFIG_IEEE802154_NRF5_EXT_IRQ_MGMT AND CONFIG_NRF_802154_SL_OPENSOURCE) diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index e944f06c805b..40ef9d08fd86 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -190,7 +190,7 @@ if(CONFIG_SOC_NRF54L_CPUAPP_COMMON) zephyr_compile_definitions("NRF_CONFIG_CPU_FREQ_MHZ=${clock_frequency_mhz}") endif() -zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54LX_SKIP_CLOCK_CONFIG NRF_SKIP_CLOCK_CONFIGURATION) +zephyr_compile_definitions_ifdef(CONFIG_NRF_SKIP_CLOCK_CONFIG NRF_SKIP_CLOCK_CONFIGURATION) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54LX_DISABLE_FICR_TRIMCNF NRF_DISABLE_FICR_TRIMCNF) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54LX_SKIP_GLITCHDETECTOR_DISABLE NRF_SKIP_GLITCHDETECTOR_DISABLE) zephyr_compile_definitions_ifndef(CONFIG_SOC_NRF54L_ANOMALY_56_WORKAROUND NRF54L_CONFIGURATION_56_ENABLE=0) diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index 0b1882ba7a65..15ba5475436c 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -281,6 +281,7 @@ config NRFX_NFCT depends on $(dt_nodelabel_exists,nfct) select NRFX_TIMER4 if SOC_SERIES_NRF52X select NRFX_TIMER2 if SOC_SERIES_NRF53X + select NRFX_TIMER24 if SOC_SERIES_NRF54LX config NRFX_NVMC bool "NVMC driver" @@ -1307,6 +1308,6 @@ endmenu config NRFX_RESERVED_RESOURCES_HEADER string - default "nrfx_reserved_resources.h" + default "nrfx_config_reserved_resources_ncs.h" endmenu # "nrfx drivers" diff --git a/modules/hal_nordic/nrfx/nrfx_config_reserved_resources_ncs.h b/modules/hal_nordic/nrfx/nrfx_config_reserved_resources_ncs.h new file mode 100644 index 000000000000..ec8a9acaf7b5 --- /dev/null +++ b/modules/hal_nordic/nrfx/nrfx_config_reserved_resources_ncs.h @@ -0,0 +1,948 @@ +/* + * Copyright (c) 2024, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NRFX_CONFIG_RESERVED_RESOURCES_H__ +#define NRFX_CONFIG_RESERVED_RESOURCES_H__ + +/** @brief Bitmask that defines GPIOTE130 channels reserved for use outside + * of the nrfx library. + */ +#define NRFX_GPIOTE130_CHANNELS_USED \ + (~NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), owned_channels) | \ + NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), child_owned_channels)) + +/** @brief Bitmask that defines GPIOTE131 channels reserved for use outside + * of the nrfx library. + */ +#define NRFX_GPIOTE131_CHANNELS_USED \ + (~NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote131), owned_channels) | \ + NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote131), child_owned_channels)) + +/** @brief Bitmask that defines EGU instances that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_EGUS_USED 0 + +/** @brief Bitmask that defines TIMER instances that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_TIMERS_USED 0 + +/* If the GRTC system timer driver is to be used, prepare definitions required + * by the nrfx_grtc driver (NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK and + * NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS) based on information from devicetree. + */ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_grtc) +#define NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK \ + (NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), owned_channels) & \ + ~NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), child_owned_channels)) +#define NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS \ + (DT_PROP_LEN_OR(DT_INST(0, nordic_nrf_grtc), owned_channels, 0) - \ + DT_PROP_LEN_OR(DT_INST(0, nordic_nrf_grtc), child_owned_channels, 0)) +#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_grtc) */ + +/* + * The enabled Bluetooth controller subsystem is responsible for providing + * definitions of the BT_CTLR_USED_* symbols used below in a file named + * bt_ctlr_used_resources.h and for adding its location to global include + * paths so that the file can be included here for all Zephyr libraries that + * are to be built. + */ +#if defined(CONFIG_BT_LL_SW_SPLIT) +#include +#if defined(CONFIG_SOC_SERIES_NRF51X) || defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_CHANNELS +#define NRFX_PPI_GROUPS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_GROUPS +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#define NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_CHANNELS +#define NRFX_DPPI0_GROUPS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_GROUPS +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#define NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_CHANNELS +#define NRFX_DPPI10_GROUPS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_GROUPS +#endif +#endif /* defined(CONFIG_BT_LL_SW_SPLIT) */ + +#if defined(CONFIG_BT_LL_SOFTDEVICE) +/* Define auxiliary symbols needed for SDC device dispatch. */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#define NRF52_SERIES +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#define NRF53_SERIES +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#define NRF54L_SERIES +#elif defined(CONFIG_SOC_SERIES_NRF71X) +#define NRF71_SERIES +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +#define NRF54H_SERIES +#endif +#include +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR SDC_PPI_CHANNELS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#define NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR SDC_DPPI_CHANNELS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) || defined(CONFIG_SOC_SERIES_NRF71X) +#define NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR SDC_DPPIC10_CHANNELS_USED_MASK +#define NRFX_DPPI00_CHANNELS_USED_BY_BT_CTLR SDC_DPPIC00_CHANNELS_USED_MASK +#define NRFX_PPIB_00_10_CHANNELS_USED_BY_BT_CTLR \ + (SDC_PPIB00_CHANNELS_USED_MASK | SDC_PPIB10_CHANNELS_USED_MASK) +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +#define NRFX_DPPI020_CHANNELS_USED_BY_BT_CTLR SDC_DPPIC020_CHANNELS_USED_MASK +#define NRFX_DPPI030_CHANNELS_USED_BY_BT_CTLR SDC_DPPIC030_CHANNELS_USED_MASK +#define NRFX_PPIB_020_030_CHANNELS_USED_BY_BT_CTLR \ + (SDC_PPIB020_CHANNELS_USED_MASK | SDC_PPIB030_CHANNELS_USED_MASK) +#else +#error Unsupported chip family +#endif +#endif /* defined(CONFIG_BT_LL_SOFTDEVICE) */ + +#if defined(CONFIG_NRF_802154_RADIO_DRIVER) +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#include <../src/nrf_802154_peripherals_nrf52.h> +#define NRFX_PPI_CHANNELS_USED_BY_802154_DRV NRF_802154_PPI_CHANNELS_USED_MASK +#define NRFX_PPI_GROUPS_USED_BY_802154_DRV NRF_802154_PPI_GROUPS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#include <../src/nrf_802154_peripherals_nrf53.h> +#define NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK +#define NRFX_DPPI0_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#include <../src/nrf_802154_peripherals_nrf54l.h> +#define NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK +#define NRFX_DPPI10_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +#include <../src/nrf_802154_peripherals_nrf54h.h> +#define NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK +#define NRFX_DPPI020_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK +#else +#error Unsupported chip family +#endif +#endif /* CONFIG_NRF_802154_RADIO_DRIVER */ + +#if defined(CONFIG_MPSL) +#include +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#define NRFX_PPI_CHANNELS_USED_BY_MPSL MPSL_PPI_CHANNELS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#define NRFX_DPPI0_CHANNELS_USED_BY_MPSL MPSL_DPPIC_CHANNELS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) || defined(CONFIG_SOC_SERIES_NRF71X) +#define NRFX_DPPI10_CHANNELS_USED_BY_MPSL MPSL_DPPIC10_CHANNELS_USED_MASK +#define NRFX_DPPI20_CHANNELS_USED_BY_MPSL MPSL_DPPIC20_CHANNELS_USED_MASK +#define NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL \ + (MPSL_PPIB11_CHANNELS_USED_MASK | MPSL_PPIB21_CHANNELS_USED_MASK) +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +#define NRFX_DPPI020_CHANNELS_USED_BY_MPSL MPSL_DPPIC020_CHANNELS_USED_MASK +#else +#error Unsupported chip family +#endif +#endif + +#ifndef NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI0_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI0_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI0_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI0_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI0_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI0_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI0_GROUPS_USED_BY_MPSL +#define NRFX_DPPI0_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI00_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI00_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI00_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI00_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI00_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI00_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI00_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI00_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI00_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI00_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI00_GROUPS_USED_BY_MPSL +#define NRFX_DPPI00_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI10_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI10_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI10_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI10_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI10_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI10_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI10_GROUPS_USED_BY_MPSL +#define NRFX_DPPI10_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI20_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI20_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI20_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI20_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI20_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI20_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI20_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI20_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI20_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI20_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI20_GROUPS_USED_BY_MPSL +#define NRFX_DPPI20_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI30_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI30_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI30_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI30_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI30_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI30_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI30_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI30_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI30_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI30_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI30_GROUPS_USED_BY_MPSL +#define NRFX_DPPI30_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI020_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI020_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI020_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI020_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI020_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI020_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI020_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI020_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI020_GROUPS_USED_BY_MPSL +#define NRFX_DPPI020_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI030_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI030_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI030_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI030_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI030_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI030_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI030_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI030_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI030_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI030_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI030_GROUPS_USED_BY_MPSL +#define NRFX_DPPI030_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI120_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI120_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI120_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI120_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI120_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI120_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI120_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI120_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI120_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI120_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI120_GROUPS_USED_BY_MPSL +#define NRFX_DPPI120_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI130_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI130_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI130_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI130_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI130_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI130_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI130_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI130_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI130_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI130_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI130_GROUPS_USED_BY_MPSL +#define NRFX_DPPI130_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI131_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI131_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI131_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI131_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI131_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI131_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI131_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI131_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI131_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI131_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI131_GROUPS_USED_BY_MPSL +#define NRFX_DPPI131_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI132_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI132_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI132_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI132_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI132_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI132_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI132_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI132_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI132_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI132_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI132_GROUPS_USED_BY_MPSL +#define NRFX_DPPI132_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI133_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI133_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI133_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI133_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI133_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI133_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI133_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI133_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI133_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI133_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI133_GROUPS_USED_BY_MPSL +#define NRFX_DPPI133_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI134_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI134_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI134_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI134_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI134_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI134_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI134_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI134_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI134_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI134_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI134_GROUPS_USED_BY_MPSL +#define NRFX_DPPI134_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI135_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI135_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI135_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI135_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI135_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI135_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI135_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI135_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI135_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI135_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI135_GROUPS_USED_BY_MPSL +#define NRFX_DPPI135_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI136_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI136_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI136_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI136_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI136_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI136_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI136_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI136_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI136_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI136_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI136_GROUPS_USED_BY_MPSL +#define NRFX_DPPI136_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPI_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPI_GROUPS_USED_BY_BT_CTLR +#define NRFX_PPI_GROUPS_USED_BY_BT_CTLR 0 +#endif + +#ifndef NRFX_PPI_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPI_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPI_GROUPS_USED_BY_802154_DRV +#define NRFX_PPI_GROUPS_USED_BY_802154_DRV 0 +#endif + +#ifndef NRFX_PPI_CHANNELS_USED_BY_MPSL +#define NRFX_PPI_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_PPI_GROUPS_USED_BY_MPSL +#define NRFX_PPI_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_00_10_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_00_10_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_00_10_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_00_10_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_00_10_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_00_10_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_01_20_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_01_20_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_01_20_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_01_20_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_01_20_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_01_20_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_11_21_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_11_21_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_11_21_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_11_21_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_22_30_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_22_30_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_22_30_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_22_30_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_22_30_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_22_30_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_02_03_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_02_03_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_02_03_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_02_03_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_02_03_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_02_03_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_04_12_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_04_12_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_04_12_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_04_12_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_04_12_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_04_12_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_020_030_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_020_030_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_020_030_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_020_030_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_020_030_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_020_030_CHANNELS_USED_BY_MPSL 0 +#endif + +#if defined(NRF_802154_VERIFY_PERIPHS_ALLOC_AGAINST_MPSL) + +BUILD_ASSERT((NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI0_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI0_GROUPS_USED_BY_802154_DRV & NRFX_DPPI0_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI00_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI00_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI00_GROUPS_USED_BY_802154_DRV & NRFX_DPPI00_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI10_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI10_GROUPS_USED_BY_802154_DRV & NRFX_DPPI10_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI20_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI20_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI20_GROUPS_USED_BY_802154_DRV & NRFX_DPPI20_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI30_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI30_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI30_GROUPS_USED_BY_802154_DRV & NRFX_DPPI30_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI020_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI020_GROUPS_USED_BY_802154_DRV & NRFX_DPPI020_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI030_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI030_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI030_GROUPS_USED_BY_802154_DRV & NRFX_DPPI030_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI120_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI120_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI120_GROUPS_USED_BY_802154_DRV & NRFX_DPPI120_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI130_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI130_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI130_GROUPS_USED_BY_802154_DRV & NRFX_DPPI130_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI131_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI131_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI131_GROUPS_USED_BY_802154_DRV & NRFX_DPPI131_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI132_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI132_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI132_GROUPS_USED_BY_802154_DRV & NRFX_DPPI132_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI133_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI133_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI133_GROUPS_USED_BY_802154_DRV & NRFX_DPPI133_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI134_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI134_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI134_GROUPS_USED_BY_802154_DRV & NRFX_DPPI134_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI135_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI135_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI135_GROUPS_USED_BY_802154_DRV & NRFX_DPPI135_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI136_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI136_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI136_GROUPS_USED_BY_802154_DRV & NRFX_DPPI136_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPI_CHANNELS_USED_BY_802154_DRV & NRFX_PPI_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPI_GROUPS_USED_BY_802154_DRV & NRFX_PPI_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_00_10_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_00_10_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_01_20_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_01_20_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_11_21_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_22_30_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_22_30_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_02_03_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_02_03_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_04_12_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_04_12_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_020_030_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_020_030_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +#endif /* NRF_802154_VERIFY_PERIPHS_ALLOC_AGAINST_MPSL */ + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI0_CHANNELS_USED \ + (NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI0_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI0_GROUPS_USED \ + (NRFX_DPPI0_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI0_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI0_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI00_CHANNELS_USED \ + (NRFX_DPPI00_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI00_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI00_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI00_GROUPS_USED \ + (NRFX_DPPI00_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI00_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI00_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI10_CHANNELS_USED \ + (NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI10_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI10_GROUPS_USED \ + (NRFX_DPPI10_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI10_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI10_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI20_CHANNELS_USED \ + (NRFX_DPPI20_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI20_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI20_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI20_GROUPS_USED \ + (NRFX_DPPI20_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI20_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI20_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI30_CHANNELS_USED \ + (NRFX_DPPI30_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI30_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI30_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI30_GROUPS_USED \ + (NRFX_DPPI30_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI30_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI30_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI020_CHANNELS_USED \ + (NRFX_DPPI020_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI020_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI020_GROUPS_USED \ + (NRFX_DPPI020_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI020_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI020_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI030_CHANNELS_USED \ + (NRFX_DPPI030_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI030_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI030_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI030_GROUPS_USED \ + (NRFX_DPPI030_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI030_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI030_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI120_CHANNELS_USED \ + (NRFX_DPPI120_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI120_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI120_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI120_GROUPS_USED \ + (NRFX_DPPI120_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI120_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI120_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI130_CHANNELS_USED \ + (NRFX_DPPI130_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI130_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI130_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI130_GROUPS_USED \ + (NRFX_DPPI130_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI130_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI130_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI131_CHANNELS_USED \ + (NRFX_DPPI131_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI131_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI131_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI131_GROUPS_USED \ + (NRFX_DPPI131_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI131_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI131_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI132_CHANNELS_USED \ + (NRFX_DPPI132_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI132_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI132_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI132_GROUPS_USED \ + (NRFX_DPPI132_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI132_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI132_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI133_CHANNELS_USED \ + (NRFX_DPPI133_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI133_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI133_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI133_GROUPS_USED \ + (NRFX_DPPI133_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI133_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI133_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI134_CHANNELS_USED \ + (NRFX_DPPI134_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI134_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI134_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI134_GROUPS_USED \ + (NRFX_DPPI134_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI134_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI134_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI135_CHANNELS_USED \ + (NRFX_DPPI135_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI135_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI135_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI135_GROUPS_USED \ + (NRFX_DPPI135_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI135_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI135_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI136_CHANNELS_USED \ + (NRFX_DPPI136_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI136_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI136_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI136_GROUPS_USED \ + (NRFX_DPPI136_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI136_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI136_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines PPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_PPI_CHANNELS_USED \ + (NRFX_PPI_CHANNELS_USED_BY_BT_CTLR | NRFX_PPI_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPI_CHANNELS_USED_BY_MPSL | NRFX_PPI_CHANNELS_USED_BY_SD) + +#define NRFX_DPPI_CHANNELS_USED NRFX_DPPI0_CHANNELS_USED +#define NRFX_DPPI_GROUPS_USED NRFX_DPPI0_GROUPS_USED + +/** @brief Bitmask that defines PPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_PPI_GROUPS_USED \ + (NRFX_PPI_GROUPS_USED_BY_BT_CTLR | NRFX_PPI_GROUPS_USED_BY_802154_DRV | \ + NRFX_PPI_GROUPS_USED_BY_MPSL | NRFX_PPI_GROUPS_USED_BY_SD) + +#define NRFX_PPIB_INTERCONNECT_00_10_CHANNELS_USED \ + (NRFX_PPIB_00_10_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_00_10_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_00_10_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_01_20_CHANNELS_USED \ + (NRFX_PPIB_01_20_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_01_20_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_01_20_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_11_21_CHANNELS_USED \ + (NRFX_PPIB_11_21_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_11_21_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_22_30_CHANNELS_USED \ + (NRFX_PPIB_22_30_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_22_30_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_22_30_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_02_03_CHANNELS_USED \ + (NRFX_PPIB_02_03_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_02_03_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_02_03_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_04_12_CHANNELS_USED \ + (NRFX_PPIB_04_12_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_04_12_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_04_12_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_020_030_CHANNELS_USED \ + (NRFX_PPIB_020_030_CHANNELS_USED_BY_BT_CTLR | \ + NRFX_PPIB_020_030_CHANNELS_USED_BY_802154_DRV | NRFX_PPIB_020_030_CHANNELS_USED_BY_MPSL) + +#if defined(CONFIG_SOFTDEVICE) +#include +#define NRFX_PPI_CHANNELS_USED_BY_SD SD_PPI_CHANNELS_USED +#define NRFX_PPI_GROUPS_USED_BY_SD SD_PPI_GROUPS_USED +#else +#define NRFX_PPI_CHANNELS_USED_BY_SD 0 +#define NRFX_PPI_GROUPS_USED_BY_SD 0 +#endif + +#endif /* NRFX_CONFIG_RESERVED_RESOURCES_H__ */ diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index aa6d5d8689f6..1aa21670bb71 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -204,7 +204,7 @@ endchoice config WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA bool "Crypto Platform Secure Architecture support for WiFi" - imply MBEDTLS_PSA_CRYPTO_C + select PSA_CRYPTO select MBEDTLS_USE_PSA_CRYPTO select PSA_WANT_ALG_ECDH select PSA_WANT_ALG_HMAC diff --git a/modules/mbedtls/CMakeLists.txt b/modules/mbedtls/CMakeLists.txt index 83a8cb674a5e..7e16f0de2514 100644 --- a/modules/mbedtls/CMakeLists.txt +++ b/modules/mbedtls/CMakeLists.txt @@ -40,6 +40,8 @@ zephyr_interface_library_named(mbedTLS) # Add regular includes target_include_directories(mbedTLS INTERFACE ${ZEPHYR_CURRENT_MODULE_DIR}/include + ${ZEPHYR_CURRENT_MODULE_DIR}/include/library + ${ZEPHYR_CURRENT_MODULE_DIR}/library configs include ) diff --git a/modules/mbedtls/Kconfig b/modules/mbedtls/Kconfig index bf165473f17f..aa8c479e89f7 100644 --- a/modules/mbedtls/Kconfig +++ b/modules/mbedtls/Kconfig @@ -29,6 +29,7 @@ choice MBEDTLS_IMPLEMENTATION config MBEDTLS_BUILTIN bool "Use Zephyr in-tree mbedTLS version" + depends on ! DISABLE_MBEDTLS_BUILTIN help Link with mbedTLS sources included with Zephyr distribution. Included mbedTLS version is well integrated with and supported @@ -42,6 +43,12 @@ config MBEDTLS_LIBRARY endchoice +config DISABLE_MBEDTLS_BUILTIN + bool + help + Subsystems cannot deselect MBEDTLS_BUILTIN, but they can select + DISABLE_MBEDTLS_BUILTIN. + config CUSTOM_MBEDTLS_CFG_FILE bool "Custom mbed TLS configuration file" help diff --git a/modules/mbedtls/Kconfig.mbedtls b/modules/mbedtls/Kconfig.mbedtls index 4a71ec496142..b4932b31635f 100644 --- a/modules/mbedtls/Kconfig.mbedtls +++ b/modules/mbedtls/Kconfig.mbedtls @@ -7,6 +7,8 @@ menu "Mbed TLS configuration" depends on MBEDTLS_BUILTIN && MBEDTLS_CFG_FILE = "config-mbedtls.h" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + menu "TLS" config MBEDTLS_TLS_VERSION_1_2 @@ -40,6 +42,8 @@ endif # MBEDTLS_TLS_VERSION_1_2 || MBEDTLS_TLS_VERSION_1_3 endmenu # TLS +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + menu "Ciphersuite configuration" comment "Supported key exchange modes" @@ -60,6 +64,8 @@ config MBEDTLS_GENPRIME_ENABLED endif # MBEDTLS_RSA_C +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_KEY_EXCHANGE_ALL_ENABLED bool "All available ciphersuite modes" select MBEDTLS_MD @@ -92,6 +98,8 @@ config MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED bool "RSA-PSK based ciphersuite modes" depends on MBEDTLS_PKCS1_V15 || MBEDTLS_PKCS1_V21 +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_PSK_MAX_LEN int "Max size of TLS pre-shared keys" default 32 @@ -99,6 +107,8 @@ config MBEDTLS_PSK_MAX_LEN Max size of TLS pre-shared keys, in bytes. It has no effect if no PSK key exchange is used. +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_KEY_EXCHANGE_RSA_ENABLED bool "RSA-only based ciphersuite modes" depends on MBEDTLS_MD @@ -107,6 +117,7 @@ config MBEDTLS_KEY_EXCHANGE_RSA_ENABLED select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT if PSA_CRYPTO_CLIENT select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT if PSA_CRYPTO_CLIENT select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE if PSA_CRYPTO_CLIENT + select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE if PSA_CRYPTO_CLIENT config MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED bool "DHE-RSA based ciphersuite modes" @@ -236,8 +247,12 @@ config MBEDTLS_ECP_NIST_OPTIM endif +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + comment "Supported ciphers and cipher modes" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_CIPHER_ALL_ENABLED bool "All available ciphers and modes" select MBEDTLS_CIPHER_AES_ENABLED @@ -268,7 +283,6 @@ config MBEDTLS_SOME_CIPHER_ENABLED config MBEDTLS_CIPHER_AES_ENABLED bool "AES block cipher" - default y if PSA_WANT_KEY_TYPE_AES && MBEDTLS_PSA_CRYPTO_C if MBEDTLS_CIPHER_AES_ENABLED @@ -328,8 +342,12 @@ config MBEDTLS_CMAC bool "CMAC (Cipher-based Message Authentication Code) mode for block ciphers." depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_DES_ENABLED +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + comment "Supported hash algorithms" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_HASH_ALL_ENABLED bool "All available MAC methods" select MBEDTLS_MD5 @@ -370,10 +388,14 @@ config MBEDTLS_SHA512 config MBEDTLS_POLY1305 bool "Poly1305 hash family" +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + endmenu comment "Random number generators" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_CTR_DRBG_ENABLED bool "CTR_DRBG AES-256-based random generator" depends on MBEDTLS_CIPHER_AES_ENABLED @@ -383,15 +405,21 @@ config MBEDTLS_HMAC_DRBG_ENABLED bool "HMAC_DRBG random generator" select MBEDTLS_MD +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + comment "Other configurations" config MBEDTLS_CIPHER bool "generic cipher layer." default y if PSA_WANT_ALG_CMAC +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_MD bool "generic message digest layer." +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_ASN1_PARSE_C bool "Support for ASN1 parser functions" @@ -431,6 +459,8 @@ config MBEDTLS_HAVE_ASM of asymmetric cryptography, however this might have an impact on the code size. +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_ENTROPY_C bool "Mbed TLS entropy accumulator" depends on MBEDTLS_SHA256 || MBEDTLS_SHA384 || MBEDTLS_SHA512 @@ -439,6 +469,8 @@ config MBEDTLS_ENTROPY_C mostly used in conjunction with CTR_DRBG or HMAC_DRBG to create a deterministic random number generator. +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_ENTROPY_POLL_ZEPHYR bool "Provide entropy data to Mbed TLS through entropy driver or random generator" default y diff --git a/modules/mbedtls/Kconfig.psa.auto b/modules/mbedtls/Kconfig.psa.auto index 08b1bbc02410..b235c30380fb 100644 --- a/modules/mbedtls/Kconfig.psa.auto +++ b/modules/mbedtls/Kconfig.psa.auto @@ -36,10 +36,6 @@ config PSA_WANT_ALG_CMAC bool "PSA_WANT_ALG_CMAC" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_ALG_CFB - bool "PSA_WANT_ALG_CFB" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_ALG_CHACHA20_POLY1305 bool "PSA_WANT_ALG_CHACHA20_POLY1305" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL @@ -60,10 +56,6 @@ config PSA_WANT_ALG_ECDH bool "PSA_WANT_ALG_ECDH" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_ALG_FFDH - bool "PSA_WANT_ALG_FFDH" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_ALG_ECDSA bool "PSA_WANT_ALG_ECDSA" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL @@ -79,6 +71,7 @@ config PSA_WANT_ALG_GCM config PSA_WANT_ALG_HKDF bool "PSA_WANT_ALG_HKDF" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_HMAC config PSA_WANT_ALG_HKDF_EXTRACT bool "PSA_WANT_ALG_HKDF_EXTRACT" if !MBEDTLS_PROMPTLESS @@ -95,22 +88,19 @@ config PSA_WANT_ALG_HMAC config PSA_WANT_ALG_MD5 bool "PSA_WANT_ALG_MD5" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_ALG_OFB - bool "PSA_WANT_ALG_OFB" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL + help + Warning: The MD5 hash is weak and deprecated and is only recommended + for use in legacy protocols. config PSA_WANT_ALG_PBKDF2_HMAC bool "PSA_WANT_ALG_PBKDF2_HMAC" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_HMAC config PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 bool "PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_ALG_RIPEMD160 - bool "PSA_WANT_ALG_RIPEMD160" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_CMAC config PSA_WANT_ALG_RSA_OAEP bool "PSA_WANT_ALG_RSA_OAEP" if !MBEDTLS_PROMPTLESS @@ -131,6 +121,9 @@ config PSA_WANT_ALG_RSA_PSS config PSA_WANT_ALG_SHA_1 bool "PSA_WANT_ALG_SHA_1" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + help + Warning: The SHA-1 hash is weak and deprecated and is only recommended + for use in legacy protocols. config PSA_WANT_ALG_SHA_224 bool "PSA_WANT_ALG_SHA_224" if !MBEDTLS_PROMPTLESS @@ -167,18 +160,22 @@ config PSA_WANT_ALG_SHA3_512 config PSA_WANT_ALG_STREAM_CIPHER bool "PSA_WANT_ALG_STREAM_CIPHER" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + select PSA_WANT_KEY_TYPE_CHACHA20 config PSA_WANT_ALG_TLS12_PRF bool "PSA_WANT_ALG_TLS12_PRF" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_HMAC config PSA_WANT_ALG_TLS12_PSK_TO_MS bool "PSA_WANT_ALG_TLS12_PSK_TO_MS" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_HMAC config PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS bool "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_SHA_256 config PSA_WANT_ECC_BRAINPOOL_P_R1_256 bool "PSA_WANT_ECC_BRAINPOOL_P_R1_256" if !MBEDTLS_PROMPTLESS @@ -228,26 +225,6 @@ config PSA_WANT_ECC_SECP_R1_521 bool "PSA_WANT_ECC_SECP_R1_521" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_DH_RFC7919_2048 - bool "PSA_WANT_DH_RFC7919_2048" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_DH_RFC7919_3072 - bool "PSA_WANT_DH_RFC7919_3072" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_DH_RFC7919_4096 - bool "PSA_WANT_DH_RFC7919_4096" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_DH_RFC7919_6144 - bool "PSA_WANT_DH_RFC7919_6144" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_DH_RFC7919_8192 - bool "PSA_WANT_DH_RFC7919_8192" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_KEY_TYPE_DERIVE bool "PSA_WANT_KEY_TYPE_DERIVE" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL @@ -268,30 +245,16 @@ config PSA_WANT_KEY_TYPE_AES bool "PSA_WANT_KEY_TYPE_AES" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_KEY_TYPE_ARIA - bool "PSA_WANT_KEY_TYPE_ARIA" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_KEY_TYPE_CAMELLIA - bool "PSA_WANT_KEY_TYPE_CAMELLIA" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_KEY_TYPE_CHACHA20 bool "PSA_WANT_KEY_TYPE_CHACHA20" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_KEY_TYPE_DES - bool "PSA_WANT_KEY_TYPE_DES" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_CHACHA20_POLY1305 || \ + PSA_WANT_ALG_STREAM_CIPHER config PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY bool "PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY - bool "PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_KEY_TYPE_RAW_DATA bool "PSA_WANT_KEY_TYPE_RAW_DATA" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL @@ -302,42 +265,42 @@ config PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT - bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT - bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE - bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL endif # PSA_CRYPTO_CLIENT diff --git a/modules/mbedtls/Kconfig.psa.logic b/modules/mbedtls/Kconfig.psa.logic index dcea9e354052..9c3a55ea3191 100644 --- a/modules/mbedtls/Kconfig.psa.logic +++ b/modules/mbedtls/Kconfig.psa.logic @@ -1,8 +1,37 @@ # Copyright (c) 2024 BayLibre SAS # SPDX-License-Identifier: Apache-2.0 -# This file extends Kconfig.psa (which is automatically generated) by adding -# some logic between PSA_WANT symbols. +config PSA_CRYPTO + bool "PSA Crypto API" + help + Enable a PSA Crypto API provider in the build. If TF-M is enabled then + it will be used for this scope, otherwise Mbed TLS will be used. + PSA_CRYPTO_PROVIDER_CUSTOM can be selected to use an out-of-tree + implementation. + +choice PSA_CRYPTO_PROVIDER + prompt "PSA Crypto API provider" + depends on PSA_CRYPTO + +config PSA_CRYPTO_PROVIDER_TFM + bool "Use TF-M" + depends on BUILD_WITH_TFM + select TFM_PARTITION_CRYPTO + +config PSA_CRYPTO_PROVIDER_MBEDTLS + bool "Use Mbed TLS" + depends on !BUILD_WITH_TFM + select MBEDTLS + select MBEDTLS_PSA_CRYPTO_C + +config PSA_CRYPTO_PROVIDER_CUSTOM + bool "Use an out-of-tree library" + depends on !BUILD_WITH_TFM + +endchoice # PSA_CRYPTO_PROVIDER + +# The following section extends Kconfig.psa.auto (which is automatically +# generated) by adding some logic between PSA_WANT symbols. config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC bool @@ -18,10 +47,3 @@ config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC depends on PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT || \ PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT || \ PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE - -config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC - bool - default y - depends on PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT || \ - PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT || \ - PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE diff --git a/modules/openthread/Kconfig b/modules/openthread/Kconfig index 99a90633f13a..afbc479b4fdd 100644 --- a/modules/openthread/Kconfig +++ b/modules/openthread/Kconfig @@ -320,7 +320,7 @@ config OPENTHREAD_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE config OPENTHREAD_CRYPTO_PSA bool "ARM PSA crypto API" - depends on MBEDTLS_PSA_CRYPTO_CLIENT + depends on PSA_CRYPTO_CLIENT select OPENTHREAD_PLATFORM_KEY_REF if !OPENTHREAD_COPROCESSOR_RCP imply OPENTHREAD_PLATFORM_KEYS_EXPORTABLE_ENABLE help diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index 55e08ee45e4a..36a734ad8b3e 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -28,6 +28,7 @@ config TFM_BOARD default "$(ZEPHYR_BASE)/modules/trusted-firmware-m/nordic/nrf5340_cpuapp" if SOC_NRF5340_CPUAPP default "$(ZEPHYR_BASE)/modules/trusted-firmware-m/nordic/nrf54l15_cpuapp" if SOC_NRF54L15_CPUAPP default "$(ZEPHYR_BASE)/modules/trusted-firmware-m/nordic/nrf54l10_cpuapp" if SOC_NRF54L10_CPUAPP + default "$(ZEPHYR_BASE)/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp" if SOC_NRF54LM20A_ENGA_CPUAPP help The board name used for building TFM. Building with TFM requires that TFM has been ported to the given board/SoC. diff --git a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules index 1d70a2c44d29..9604319ca012 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules +++ b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules @@ -10,6 +10,7 @@ if TFM_PARTITION_CRYPTO config TFM_CRYPTO_RNG_MODULE_ENABLED bool "Random number generator crypto module" default y + depends on PSA_WANT_GENERATE_RANDOM && NRF_SECURITY help Enables the random number generator module within the crypto partition. Unset this option if 'psa_generate_random' is not used. @@ -17,6 +18,7 @@ config TFM_CRYPTO_RNG_MODULE_ENABLED config TFM_CRYPTO_KEY_MODULE_ENABLED bool "KEY crypto module" default y + depends on PSA_HAS_KEY_SUPPORT && NRF_SECURITY help Enables the KEY crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_key_management.c' @@ -25,6 +27,7 @@ config TFM_CRYPTO_KEY_MODULE_ENABLED config TFM_CRYPTO_AEAD_MODULE_ENABLED bool "AEAD crypto module" default y + depends on PSA_HAS_AEAD_SUPPORT && NRF_SECURITY help Enables the AEAD crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_aead.c' @@ -33,6 +36,7 @@ config TFM_CRYPTO_AEAD_MODULE_ENABLED config TFM_CRYPTO_MAC_MODULE_ENABLED bool "MAC crypto module" default y + depends on PSA_HAS_MAC_SUPPORT && NRF_SECURITY help Enables the MAC crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_mac.c' @@ -41,6 +45,7 @@ config TFM_CRYPTO_MAC_MODULE_ENABLED config TFM_CRYPTO_HASH_MODULE_ENABLED bool "HASH crypto module" default y + depends on PSA_HAS_HASH_SUPPORT && NRF_SECURITY help Enables the HASH crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_hash.c' @@ -49,6 +54,7 @@ config TFM_CRYPTO_HASH_MODULE_ENABLED config TFM_CRYPTO_CIPHER_MODULE_ENABLED bool "CIPHER crypto module" default y + depends on PSA_HAS_CIPHER_SUPPORT && NRF_SECURITY help Enables the CIPHER crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_cipher.c' @@ -57,6 +63,7 @@ config TFM_CRYPTO_CIPHER_MODULE_ENABLED config TFM_CRYPTO_ASYM_ENCRYPT_MODULE_ENABLED bool "ASYM ENCRYPT crypto module" default y + depends on PSA_HAS_ASYM_ENCRYPT_SUPPORT && NRF_SECURITY help Enables the ASYM ENCRYPT crypto module within the crypto partition. Unset this option if the encrypt functionality provided by 'crypto_asymmetric.c' @@ -65,6 +72,7 @@ config TFM_CRYPTO_ASYM_ENCRYPT_MODULE_ENABLED config TFM_CRYPTO_ASYM_SIGN_MODULE_ENABLED bool "ASYM SIGN crypto module" default y + depends on PSA_HAS_ASYM_SIGN_SUPPORT && NRF_SECURITY help Enables the ASYM SIGN crypto module within the crypto partition. Unset this option if the sign functionality provided by 'crypto_asymmetric.c' @@ -73,10 +81,23 @@ config TFM_CRYPTO_ASYM_SIGN_MODULE_ENABLED config TFM_CRYPTO_KEY_DERIVATION_MODULE_ENABLED bool "KEY DERIVATION crypto module" default y + depends on (PSA_HAS_KEY_DERIVATION || PSA_HAS_KEY_AGREEMENT) && NRF_SECURITY help Enables the KEY_DERIVATION crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_key_derivation.c' is not used. + Note that key agreement is under key derivation in the current implementation. + +config TFM_CRYPTO_PAKE_MODULE_ENABLED + bool "PAKE crypto module" + default y + depends on PSA_HAS_PAKE_SUPPORT + depends on NRF_SECURITY + depends on PSA_CRYPTO_DRIVER_OBERON || PSA_CRYPTO_DRIVER_CRACEN + help + Enables the PAKE crypto module within the crypto partition. + Unset this option if the functionality provided by 'crypto_pake.c' + is not used. endif # TFM_PARTITION_CRYPTO diff --git a/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/CMakeLists.txt b/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/CMakeLists.txt new file mode 100644 index 000000000000..c926ace19c8f --- /dev/null +++ b/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (c) 2025, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(NRF_BOARD_SELECTED True) + +add_subdirectory(${Trusted\ Firmware\ M_SOURCE_DIR}/platform/ext/target/nordic_nrf/common/nrf54lm20a nrf54lm20a) + +add_subdirectory(.. common) + +install(FILES ${CMAKE_CURRENT_LIST_DIR}/ns/cpuarch_ns.cmake + DESTINATION ${INSTALL_PLATFORM_NS_DIR} + RENAME cpuarch.cmake) + +install(FILES config.cmake + DESTINATION ${INSTALL_PLATFORM_NS_DIR}) + +install(DIRECTORY ${Trusted\ Firmware\ M_SOURCE_DIR}/platform/ext/target/nordic_nrf/nrf54lm20dk_nrf54lm20a_cpuapp/tests + + DESTINATION ${INSTALL_PLATFORM_NS_DIR} +) diff --git a/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/config.cmake b/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/config.cmake new file mode 100644 index 000000000000..4b1e3ab5e97c --- /dev/null +++ b/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/config.cmake @@ -0,0 +1,9 @@ +# +# Copyright (c) 2025, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(NRF_SOC_VARIANT nrf54lm20a CACHE STRING "nRF SoC Variant") + +include(${PLATFORM_PATH}/common/nrf54lm20a/config.cmake) diff --git a/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/cpuarch.cmake b/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/cpuarch.cmake new file mode 100644 index 000000000000..1766b89f9964 --- /dev/null +++ b/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/cpuarch.cmake @@ -0,0 +1,9 @@ +# +# Copyright (c) 2025, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(PLATFORM_PATH platform/ext/target/nordic_nrf) + +include(${PLATFORM_PATH}/common/nrf54lm20a/cpuarch.cmake) diff --git a/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/ns/cpuarch_ns.cmake b/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/ns/cpuarch_ns.cmake new file mode 100644 index 000000000000..cec0a5536dd3 --- /dev/null +++ b/modules/trusted-firmware-m/nordic/nrf54lm20a_cpuapp/ns/cpuarch_ns.cmake @@ -0,0 +1,10 @@ +# +# Copyright (c) 2025, Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(PLATFORM_DIR ${CMAKE_CURRENT_LIST_DIR}) +set(PLATFORM_PATH ${CMAKE_CURRENT_LIST_DIR}) + +include(${CMAKE_CURRENT_LIST_DIR}/common/nrf54lm20a/cpuarch.cmake) diff --git a/modules/uoscore-uedhoc/Kconfig b/modules/uoscore-uedhoc/Kconfig index 06eaecd7b210..766249553188 100644 --- a/modules/uoscore-uedhoc/Kconfig +++ b/modules/uoscore-uedhoc/Kconfig @@ -5,7 +5,6 @@ menuconfig UOSCORE bool "UOSCORE library" depends on ZCBOR depends on ZCBOR_CANONICAL - depends on MBEDTLS select UOSCORE_UEDHOC_CRYPTO_COMMON help @@ -22,7 +21,6 @@ menuconfig UEDHOC bool "UEDHOC library" depends on ZCBOR depends on ZCBOR_CANONICAL - depends on MBEDTLS select UOSCORE_UEDHOC_CRYPTO_COMMON help This option enables the UEDHOC library. @@ -38,7 +36,7 @@ if UOSCORE || UEDHOC config UOSCORE_UEDHOC_CRYPTO_COMMON bool - imply MBEDTLS_PSA_CRYPTO_C if !BUILD_WITH_TFM + select PSA_CRYPTO select PSA_WANT_ALG_ECDH select PSA_WANT_ALG_ECDSA select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT diff --git a/samples/basic/blinky/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/samples/basic/blinky/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..cbc7b679be00 --- /dev/null +++ b/samples/basic/blinky/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/ { + aliases { + led0 = &led0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio9 0 GPIO_ACTIVE_HIGH>; + label = "Green LED 0"; + }; + }; +}; + +&gpiote130 { + status = "okay"; +}; + +&gpio9 { + status = "okay"; +}; diff --git a/samples/basic/blinky/boards/nrf54l15dk_nrf54l15_cpuapp_hpf_gpio.overlay b/samples/basic/blinky/boards/nrf54l15dk_nrf54l15_cpuapp_hpf_gpio.overlay new file mode 100644 index 000000000000..bd1ceb2f8945 --- /dev/null +++ b/samples/basic/blinky/boards/nrf54l15dk_nrf54l15_cpuapp_hpf_gpio.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&led0 { + gpios = <&hpf_gpio 9 GPIO_ACTIVE_HIGH>; +}; diff --git a/samples/bluetooth/bap_broadcast_sink/sample.yaml b/samples/bluetooth/bap_broadcast_sink/sample.yaml index 5d06dee0bf89..148b8b641697 100644 --- a/samples/bluetooth/bap_broadcast_sink/sample.yaml +++ b/samples/bluetooth/bap_broadcast_sink/sample.yaml @@ -24,5 +24,7 @@ tests: - nrf52_bsim - nrf52833dk/nrf52833 - nrf52840dongle/nrf52840 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/bap_broadcast_sink/sysbuild.cmake b/samples/bluetooth/bap_broadcast_sink/sysbuild.cmake index 2523aac8ea76..d5d260789ff7 100644 --- a/samples/bluetooth/bap_broadcast_sink/sysbuild.cmake +++ b/samples/bluetooth/bap_broadcast_sink/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/bap_broadcast_source/sample.yaml b/samples/bluetooth/bap_broadcast_source/sample.yaml index 5e5b01d942d0..5f745cd08950 100644 --- a/samples/bluetooth/bap_broadcast_source/sample.yaml +++ b/samples/bluetooth/bap_broadcast_source/sample.yaml @@ -36,5 +36,7 @@ tests: - nrf52_bsim - nrf52833dk/nrf52833 - nrf52840dongle/nrf52840 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/bap_broadcast_source/sysbuild.cmake b/samples/bluetooth/bap_broadcast_source/sysbuild.cmake index 2523aac8ea76..d5d260789ff7 100644 --- a/samples/bluetooth/bap_broadcast_source/sysbuild.cmake +++ b/samples/bluetooth/bap_broadcast_source/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/bap_unicast_client/sample.yaml b/samples/bluetooth/bap_unicast_client/sample.yaml index 7283090b8781..44f32934ce99 100644 --- a/samples/bluetooth/bap_unicast_client/sample.yaml +++ b/samples/bluetooth/bap_unicast_client/sample.yaml @@ -22,5 +22,7 @@ tests: - nrf52840dk/nrf52840 integration_platforms: - nrf52dk/nrf52832 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/bap_unicast_client/sysbuild.cmake b/samples/bluetooth/bap_unicast_client/sysbuild.cmake index 2523aac8ea76..d5d260789ff7 100644 --- a/samples/bluetooth/bap_unicast_client/sysbuild.cmake +++ b/samples/bluetooth/bap_unicast_client/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/bap_unicast_server/sample.yaml b/samples/bluetooth/bap_unicast_server/sample.yaml index 068f752b626b..266ced73f66d 100644 --- a/samples/bluetooth/bap_unicast_server/sample.yaml +++ b/samples/bluetooth/bap_unicast_server/sample.yaml @@ -22,5 +22,7 @@ tests: - nrf52840dk/nrf52840 integration_platforms: - nrf52dk/nrf52832 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/bap_unicast_server/sysbuild.cmake b/samples/bluetooth/bap_unicast_server/sysbuild.cmake index 2523aac8ea76..d5d260789ff7 100644 --- a/samples/bluetooth/bap_unicast_server/sysbuild.cmake +++ b/samples/bluetooth/bap_unicast_server/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/beacon/sample.yaml b/samples/bluetooth/beacon/sample.yaml index 23ffad73c796..00215341924f 100644 --- a/samples/bluetooth/beacon/sample.yaml +++ b/samples/bluetooth/beacon/sample.yaml @@ -20,7 +20,9 @@ tests: - ophelia4ev/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp sample.bluetooth.beacon-coex: - extra_args: CONF_FILE="prj-coex.conf" + extra_args: + - CONF_FILE="prj-coex.conf" + - SNIPPET="bt-ll-sw-split" harness: bluetooth platform_allow: - nrf52840dk/nrf52840 diff --git a/samples/bluetooth/cap_acceptor/sample.yaml b/samples/bluetooth/cap_acceptor/sample.yaml index 824e744eecaf..9061f44679fb 100644 --- a/samples/bluetooth/cap_acceptor/sample.yaml +++ b/samples/bluetooth/cap_acceptor/sample.yaml @@ -26,5 +26,7 @@ tests: - nrf52833dk/nrf52833 - nrf52840dk/nrf52840 - nrf52840dongle/nrf52840 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/cap_acceptor/sysbuild.cmake b/samples/bluetooth/cap_acceptor/sysbuild.cmake index 2523aac8ea76..d5d260789ff7 100644 --- a/samples/bluetooth/cap_acceptor/sysbuild.cmake +++ b/samples/bluetooth/cap_acceptor/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/cap_initiator/sample.yaml b/samples/bluetooth/cap_initiator/sample.yaml index b4f593c99129..e3e557f48301 100644 --- a/samples/bluetooth/cap_initiator/sample.yaml +++ b/samples/bluetooth/cap_initiator/sample.yaml @@ -26,5 +26,7 @@ tests: - nrf52833dk/nrf52833 - nrf52840dk/nrf52840 - nrf52840dongle/nrf52840 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/cap_initiator/sysbuild.cmake b/samples/bluetooth/cap_initiator/sysbuild.cmake index 2523aac8ea76..d5d260789ff7 100644 --- a/samples/bluetooth/cap_initiator/sysbuild.cmake +++ b/samples/bluetooth/cap_initiator/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/direction_finding_central/sample.yaml b/samples/bluetooth/direction_finding_central/sample.yaml index b7a118e6cdc8..ffdf634c6e3e 100644 --- a/samples/bluetooth/direction_finding_central/sample.yaml +++ b/samples/bluetooth/direction_finding_central/sample.yaml @@ -14,15 +14,24 @@ tests: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - nrf5340dk/nrf5340/cpuapp - sample.bluetooth.direction_finding.central.aod: + sample.bluetooth.direction_finding.central.aod_with_controller: harness: bluetooth - extra_args: EXTRA_CONF_FILE="overlay-aod.conf" + extra_args: + - EXTRA_CONF_FILE="overlay-aod.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - - nrf5340dk/nrf5340/cpuapp tags: bluetooth integration_platforms: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 + sample.bluetooth.direction_finding.central.aod_host_only: + harness: bluetooth + extra_args: + - OVERLAY_CONFIG="overlay-aod.conf" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + integration_platforms: - nrf5340dk/nrf5340/cpuapp diff --git a/samples/bluetooth/direction_finding_connectionless_rx/sample.yaml b/samples/bluetooth/direction_finding_connectionless_rx/sample.yaml index 8e6097de58ae..c500cc80dcec 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/sample.yaml +++ b/samples/bluetooth/direction_finding_connectionless_rx/sample.yaml @@ -12,14 +12,22 @@ tests: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - nrf5340dk/nrf5340/cpuapp - sample.bluetooth.direction_finding_connectionless_rx.aod: + sample.bluetooth.direction_finding_connectionless_rx.aod_with_controller: harness: bluetooth - extra_args: EXTRA_CONF_FILE="overlay-aod.conf" + extra_args: + - EXTRA_CONF_FILE="overlay-aod.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - - nrf5340dk/nrf5340/cpuapp integration_platforms: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 + sample.bluetooth.direction_finding_connectionless_rx.aod_host_only: + harness: bluetooth + extra_args: + - OVERLAY_CONFIG="overlay-aod.conf" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: - nrf5340dk/nrf5340/cpuapp diff --git a/samples/bluetooth/direction_finding_connectionless_tx/sample.yaml b/samples/bluetooth/direction_finding_connectionless_tx/sample.yaml index 78d21b2c95f5..2a4fa93d19d5 100644 --- a/samples/bluetooth/direction_finding_connectionless_tx/sample.yaml +++ b/samples/bluetooth/direction_finding_connectionless_tx/sample.yaml @@ -12,14 +12,22 @@ tests: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - nrf5340dk/nrf5340/cpuapp - sample.bluetooth.direction_finding_connectionless.aoa: + sample.bluetooth.direction_finding_connectionless.aoa_with_controller: harness: bluetooth - extra_args: EXTRA_CONF_FILE="overlay-aoa.conf" + extra_args: + - EXTRA_CONF_FILE="overlay-aoa.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - - nrf5340dk/nrf5340/cpuapp integration_platforms: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 + sample.bluetooth.direction_finding_connectionless.aoa_host_only: + harness: bluetooth + extra_args: + - OVERLAY_CONFIG="overlay-aoa.conf" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: - nrf5340dk/nrf5340/cpuapp diff --git a/samples/bluetooth/direction_finding_peripheral/sample.yaml b/samples/bluetooth/direction_finding_peripheral/sample.yaml index f300cb415cc5..01f612ad08a0 100644 --- a/samples/bluetooth/direction_finding_peripheral/sample.yaml +++ b/samples/bluetooth/direction_finding_peripheral/sample.yaml @@ -14,15 +14,24 @@ tests: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - nrf5340dk/nrf5340/cpuapp - sample.bluetooth.direction_finding.peripheral.aod: + sample.bluetooth.direction_finding.peripheral.aod_with_controller: harness: bluetooth - extra_args: EXTRA_CONF_FILE="overlay-aoa.conf" + extra_args: + - EXTRA_CONF_FILE="overlay-aoa.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - - nrf5340dk/nrf5340/cpuapp tags: bluetooth integration_platforms: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 + sample.bluetooth.direction_finding.peripheral.aod_host_only: + harness: bluetooth + extra_args: + - OVERLAY_CONFIG="overlay-aoa.conf" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + integration_platforms: - nrf5340dk/nrf5340/cpuapp diff --git a/samples/bluetooth/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf b/samples/bluetooth/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 000000000000..296e68366389 --- /dev/null +++ b/samples/bluetooth/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1,2 @@ +# Increase stack size for Cracen driver. +CONFIG_MAIN_STACK_SIZE=1024 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf index 9e3225621842..2827eeeeab23 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf @@ -44,8 +44,9 @@ CONFIG_BT_ISO_RX_BUF_COUNT=1 # Controller CONFIG_BT_LL_SW_SPLIT=y -CONFIG_BT_CTLR_ASSERT_HANDLER=y CONFIG_BT_CTLR_DTM_HCI=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y # Rx ACL and Adv Reports CONFIG_BT_CTLR_RX_BUFFERS=9 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf index 89ba46ff357a..1ba04dc5dd5b 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf @@ -12,6 +12,8 @@ CONFIG_BT_MAX_CONN=16 # Controller CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y # Disable unused Bluetooth features CONFIG_BT_CTLR_DUP_FILTER_LEN=0 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf index 740de0cc83eb..1f652ddbeb58 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf @@ -43,8 +43,9 @@ CONFIG_BT_ISO_RX_BUF_COUNT=1 # Controller CONFIG_BT_LL_SW_SPLIT=y -CONFIG_BT_CTLR_ASSERT_HANDLER=y CONFIG_BT_CTLR_DTM_HCI=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y # Rx ACL and Adv Reports CONFIG_BT_CTLR_RX_BUFFERS=9 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf index 663751c16e65..7a6f8544986b 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf @@ -29,8 +29,9 @@ CONFIG_BT_MAX_CONN=2 # Controller CONFIG_BT_LL_SW_SPLIT=y -CONFIG_BT_CTLR_ASSERT_HANDLER=y CONFIG_BT_CTLR_DTM_HCI=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y # Rx ACL and Adv Reports CONFIG_BT_CTLR_RX_BUFFERS=9 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf index 710530568acb..6016318536bc 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf @@ -53,8 +53,9 @@ CONFIG_BT_ISO_RX_BUF_COUNT=1 # Controller CONFIG_BT_LL_SW_SPLIT=y -CONFIG_BT_CTLR_ASSERT_HANDLER=y CONFIG_BT_CTLR_DTM_HCI=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y # Rx ACL and Adv Reports CONFIG_BT_CTLR_RX_BUFFERS=9 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf index c63928dd27ca..015a0e102f71 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf @@ -30,6 +30,8 @@ CONFIG_BT_ISO_RX_BUF_COUNT=1 # ISO Broadcast Controller CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 CONFIG_BT_CTLR_ADV_ISO=y diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf index 55e680990eed..6f84bc3d7cfe 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf @@ -40,6 +40,8 @@ CONFIG_BT_ISO_RX_BUF_COUNT=1 # Controller CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf index 0031111ede82..3629ee8c9176 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf @@ -40,6 +40,8 @@ CONFIG_BT_ISO_RX_BUF_COUNT=1 # Controller CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf index c0922ba9f932..1b2e85e7a604 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf @@ -22,6 +22,8 @@ CONFIG_BT_PERIPHERAL=n # ISO Receive Controller CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y CONFIG_BT_CTLR_SYNC_PERIODIC=y CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 CONFIG_BT_CTLR_SYNC_ISO=y diff --git a/samples/bluetooth/hci_ipc/nrf54h20_cpurad-bt_ll_softdevice.conf b/samples/bluetooth/hci_ipc/nrf54h20_cpurad-bt_ll_softdevice.conf new file mode 100644 index 000000000000..1f7748e5cd7d --- /dev/null +++ b/samples/bluetooth/hci_ipc/nrf54h20_cpurad-bt_ll_softdevice.conf @@ -0,0 +1,33 @@ +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_ISR_STACK_SIZE=1024 +CONFIG_IDLE_STACK_SIZE=256 +CONFIG_MAIN_STACK_SIZE=512 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_IPC_SERVICE_BACKEND_RPMSG_WQ_STACK_SIZE=512 +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y + +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +# Host +CONFIG_BT_BROADCASTER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PER_ADV=y +CONFIG_BT_PER_ADV_SYNC=y + +# Controller +CONFIG_BT_LL_SW_SPLIT=n +CONFIG_BT_LL_SOFTDEVICE=y +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 diff --git a/samples/bluetooth/hci_ipc/sample.yaml b/samples/bluetooth/hci_ipc/sample.yaml index b758b2547688..3763478b6b33 100644 --- a/samples/bluetooth/hci_ipc/sample.yaml +++ b/samples/bluetooth/hci_ipc/sample.yaml @@ -15,7 +15,9 @@ tests: sample.bluetooth.hci_ipc.iso_broadcast.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -25,7 +27,9 @@ tests: sample.bluetooth.hci_ipc.iso_receive.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -35,7 +39,9 @@ tests: sample.bluetooth.hci_ipc.bis.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_bis-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_bis-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -45,7 +51,9 @@ tests: sample.bluetooth.hci_ipc.iso_central.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_central-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso_central-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -55,7 +63,9 @@ tests: sample.bluetooth.hci_ipc.iso_peripheral.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -65,7 +75,9 @@ tests: sample.bluetooth.hci_ipc.cis.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_cis-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_cis-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -75,7 +87,9 @@ tests: sample.bluetooth.hci_ipc.iso.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -99,6 +113,7 @@ tests: extra_args: - CONF_FILE="nrf5340_cpunet_df-bt_ll_sw_split.conf" - DTC_OVERLAY_FILE="nrf5340_cpunet_df-bt_ll_sw_split.overlay" + - SNIPPET="bt-ll-sw-split" platform_allow: nrf5340dk/nrf5340/cpunet integration_platforms: - nrf5340dk/nrf5340/cpunet @@ -109,13 +124,16 @@ tests: - CONF_FILE="nrf5340_cpunet_df-bt_ll_sw_split.conf" - DTC_OVERLAY_FILE="nrf5340_cpunet_df-bt_ll_sw_split.overlay" - CONFIG_BT_CTLR_PHY_CODED=n + - SNIPPET="bt-ll-sw-split" platform_allow: nrf5340dk/nrf5340/cpunet integration_platforms: - nrf5340dk/nrf5340/cpunet sample.bluetooth.hci_ipc.mesh.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: nrf5340dk/nrf5340/cpunet integration_platforms: - nrf5340dk/nrf5340/cpunet diff --git a/samples/bluetooth/hci_ipc/src/main.c b/samples/bluetooth/hci_ipc/src/main.c index 3641d5d98968..1dd941b58bd9 100644 --- a/samples/bluetooth/hci_ipc/src/main.c +++ b/samples/bluetooth/hci_ipc/src/main.c @@ -307,7 +307,10 @@ void bt_ctlr_assert_handle(char *file, uint32_t line) LOG_PANIC(); while (true) { + k_cpu_idle(); }; + + CODE_UNREACHABLE; } #endif /* CONFIG_BT_CTLR_ASSERT_HANDLER */ @@ -338,6 +341,7 @@ void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf) LOG_PANIC(); while (true) { + k_cpu_idle(); }; CODE_UNREACHABLE; diff --git a/samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf b/samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf new file mode 100644 index 000000000000..e6749ae63990 --- /dev/null +++ b/samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf @@ -0,0 +1 @@ +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y diff --git a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf index 05fbeb7be780..e5b65559919c 100644 --- a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf @@ -28,8 +28,9 @@ CONFIG_BT_ISO_RX_BUF_COUNT=1 # Controller CONFIG_BT_LL_SW_SPLIT=y -CONFIG_BT_CTLR_ASSERT_HANDLER=y CONFIG_BT_CTLR_DTM_HCI=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_HCI_VS_FATAL_ERROR=y # Rx ACL and Adv Reports CONFIG_BT_CTLR_RX_BUFFERS=9 diff --git a/samples/bluetooth/hci_uart/sample.yaml b/samples/bluetooth/hci_uart/sample.yaml index df2b40135c67..8555c65cf0df 100644 --- a/samples/bluetooth/hci_uart/sample.yaml +++ b/samples/bluetooth/hci_uart/sample.yaml @@ -24,7 +24,9 @@ tests: platform_allow: nrf52833dk/nrf52833 integration_platforms: - nrf52833dk/nrf52833 - extra_args: DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + extra_args: + - DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + - SNIPPET="bt-ll-sw-split" extra_configs: - CONFIG_BT_CTLR_DF=y tags: @@ -33,7 +35,9 @@ tests: sample.bluetooth.hci_uart.nrf5340_netcore.df: harness: bluetooth platform_allow: nrf5340dk/nrf5340/cpunet - extra_args: DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + extra_args: + - DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + - SNIPPET="bt-ll-sw-split" extra_configs: - CONFIG_BT_CTLR_DF=y tags: @@ -44,7 +48,9 @@ tests: platform_allow: nrf52833dk/nrf52833 integration_platforms: - nrf52833dk/nrf52833 - extra_args: DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + extra_args: + - DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + - SNIPPET="bt-ll-sw-split" extra_configs: - CONFIG_BT_CTLR_DF=y - CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT=y @@ -54,7 +60,9 @@ tests: sample.bluetooth.hci_uart.nrf5340_netcore.df.iq_report: harness: bluetooth platform_allow: nrf5340dk/nrf5340/cpunet - extra_args: DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + extra_args: + - DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + - SNIPPET="bt-ll-sw-split" extra_configs: - CONFIG_BT_CTLR_DF=y - CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT=y @@ -88,6 +96,7 @@ tests: extra_args: - EXTRA_CONF_FILE=overlay-all-bt_ll_sw_split.conf - DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + - SNIPPET="bt-ll-sw-split" tags: - uart - bluetooth @@ -99,6 +108,7 @@ tests: extra_args: - EXTRA_CONF_FILE=overlay-all-bt_ll_sw_split.conf - DTC_OVERLAY_FILE=./boards/nrf54l15dk_nrf54l15_cpuapp_df.overlay + - SNIPPET="bt-ll-sw-split" tags: - uart - bluetooth diff --git a/samples/bluetooth/hci_vs_scan_req/sample.yaml b/samples/bluetooth/hci_vs_scan_req/sample.yaml index 245a83aa0d96..49526522d16e 100644 --- a/samples/bluetooth/hci_vs_scan_req/sample.yaml +++ b/samples/bluetooth/hci_vs_scan_req/sample.yaml @@ -9,4 +9,6 @@ tests: - nrf52dk/nrf52832 extra_configs: - CONFIG_BT_LL_SW_SPLIT=y + extra_args: + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/iso_central/sample.yaml b/samples/bluetooth/iso_central/sample.yaml index 3a7dedd404ae..57254ee809ab 100644 --- a/samples/bluetooth/iso_central/sample.yaml +++ b/samples/bluetooth/iso_central/sample.yaml @@ -11,11 +11,11 @@ tests: sample.bluetooth.iso_central.bt_ll_sw_split: harness: bluetooth platform_allow: - - qemu_cortex_m3 - - qemu_x86 - nrf52_bsim - nrf52833dk/nrf52833 integration_platforms: - nrf52833dk/nrf52833 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/mesh/boards/qemu_x86.conf b/samples/bluetooth/mesh/boards/qemu_x86.conf new file mode 100644 index 000000000000..bfb57193b782 --- /dev/null +++ b/samples/bluetooth/mesh/boards/qemu_x86.conf @@ -0,0 +1,6 @@ +# nrf_security only supports Cortex-M via PSA crypto libraries. +# Enforcing usage of built-in Mbed TLS for native simulator. +CONFIG_NRF_SECURITY=n +CONFIG_MBEDTLS_ENABLE_HEAP=n +CONFIG_TRUSTED_STORAGE=n +CONFIG_SECURE_STORAGE=y diff --git a/samples/bluetooth/mesh/prj.conf b/samples/bluetooth/mesh/prj.conf index 14b19316a866..cd7d6532b614 100644 --- a/samples/bluetooth/mesh/prj.conf +++ b/samples/bluetooth/mesh/prj.conf @@ -5,7 +5,7 @@ CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y CONFIG_HWINFO=y CONFIG_BT=y diff --git a/samples/bluetooth/mesh/src/main.c b/samples/bluetooth/mesh/src/main.c index cec8159e292a..02decb8585e2 100644 --- a/samples/bluetooth/mesh/src/main.c +++ b/samples/bluetooth/mesh/src/main.c @@ -267,9 +267,16 @@ static const struct bt_mesh_comp comp = { }; /* Provisioning */ - -static int output_number(bt_mesh_output_action_t action, uint32_t number) +static int output_numeric(bt_mesh_output_action_t action, uint8_t *numeric, size_t size) { + uint32_t number; + + if (size != sizeof(number)) { + printk("Wrong OOB size: %u\n", size); + return -EINVAL; + } + + number = sys_get_le32(numeric); printk("OOB Number: %u\n", number); board_output_number(action, number); @@ -293,7 +300,7 @@ static const struct bt_mesh_prov prov = { .uuid = dev_uuid, .output_size = 4, .output_actions = BT_MESH_DISPLAY_NUMBER, - .output_number = output_number, + .output_numeric = output_numeric, .complete = prov_complete, .reset = prov_reset, }; diff --git a/samples/bluetooth/mesh_demo/boards/qemu_x86.conf b/samples/bluetooth/mesh_demo/boards/qemu_x86.conf new file mode 100644 index 000000000000..bfb57193b782 --- /dev/null +++ b/samples/bluetooth/mesh_demo/boards/qemu_x86.conf @@ -0,0 +1,6 @@ +# nrf_security only supports Cortex-M via PSA crypto libraries. +# Enforcing usage of built-in Mbed TLS for native simulator. +CONFIG_NRF_SECURITY=n +CONFIG_MBEDTLS_ENABLE_HEAP=n +CONFIG_TRUSTED_STORAGE=n +CONFIG_SECURE_STORAGE=y diff --git a/samples/bluetooth/mesh_demo/prj.conf b/samples/bluetooth/mesh_demo/prj.conf index bcb738ae5bd1..b7016b02c65b 100644 --- a/samples/bluetooth/mesh_demo/prj.conf +++ b/samples/bluetooth/mesh_demo/prj.conf @@ -31,7 +31,7 @@ CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y CONFIG_BT_MESH_RPL_STORE_TIMEOUT=600 -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y # Limit the number of key slots in PSA Crypto core to reduce # RAM footprint diff --git a/samples/bluetooth/mesh_provisioner/boards/qemu_x86.conf b/samples/bluetooth/mesh_provisioner/boards/qemu_x86.conf new file mode 100644 index 000000000000..bfb57193b782 --- /dev/null +++ b/samples/bluetooth/mesh_provisioner/boards/qemu_x86.conf @@ -0,0 +1,6 @@ +# nrf_security only supports Cortex-M via PSA crypto libraries. +# Enforcing usage of built-in Mbed TLS for native simulator. +CONFIG_NRF_SECURITY=n +CONFIG_MBEDTLS_ENABLE_HEAP=n +CONFIG_TRUSTED_STORAGE=n +CONFIG_SECURE_STORAGE=y diff --git a/samples/bluetooth/mesh_provisioner/prj.conf b/samples/bluetooth/mesh_provisioner/prj.conf index 10949c5480db..0e5f6490edee 100644 --- a/samples/bluetooth/mesh_provisioner/prj.conf +++ b/samples/bluetooth/mesh_provisioner/prj.conf @@ -1,6 +1,10 @@ #CONFIG_INIT_STACKS=y -CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 +# Stack sizes from thread analysis + 50% margin, rounded to nearest 100 +CONFIG_MAIN_STACK_SIZE=4400 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4800 +CONFIG_BT_MESH_SETTINGS_WORKQ_STACK_SIZE=1700 +CONFIG_BT_MESH_ADV_STACK_SIZE=4000 +CONFIG_BT_RX_STACK_SIZE=3300 # The Bluetooth API should not be used from a preemptive thread: CONFIG_MAIN_THREAD_PRIORITY=-2 @@ -45,7 +49,7 @@ CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y CONFIG_BT_MESH_RPL_STORE_TIMEOUT=600 -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y #CONFIG_BT_MESH_LOG_LEVEL_DBG=y #CONFIG_BT_MESH_SETTINGS_LOG_LEVEL_DBG=y diff --git a/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml b/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml index d7c816ee5b76..901d40b00d4f 100644 --- a/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml +++ b/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml @@ -23,5 +23,7 @@ tests: integration_platforms: - nrf52_bsim - nrf52833dk/nrf52833 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake b/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake index 2523aac8ea76..d5d260789ff7 100644 --- a/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake +++ b/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/pbp_public_broadcast_source/sample.yaml b/samples/bluetooth/pbp_public_broadcast_source/sample.yaml index 80c907042119..1d2e31306e29 100644 --- a/samples/bluetooth/pbp_public_broadcast_source/sample.yaml +++ b/samples/bluetooth/pbp_public_broadcast_source/sample.yaml @@ -23,5 +23,7 @@ tests: integration_platforms: - nrf52_bsim - nrf52833dk/nrf52833 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake b/samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake index d3bf7be5b6c3..e0a7fd9d175d 100644 --- a/samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake +++ b/samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake @@ -18,6 +18,10 @@ if(NOT("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "")) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/peripheral_ans/CMakeLists.txt b/samples/bluetooth/peripheral_ans/CMakeLists.txt new file mode 100644 index 000000000000..7bbc26196724 --- /dev/null +++ b/samples/bluetooth/peripheral_ans/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(peripheral_ans) + +target_sources(app PRIVATE + src/main.c +) diff --git a/samples/bluetooth/peripheral_ans/README.rst b/samples/bluetooth/peripheral_ans/README.rst new file mode 100644 index 000000000000..409de9716a3a --- /dev/null +++ b/samples/bluetooth/peripheral_ans/README.rst @@ -0,0 +1,26 @@ +.. zephyr:code-sample:: ble_peripheral_ans + :name: Peripheral ANS + :relevant-api: bluetooth + + Send notification using Alert Notification Service (ANS). + +Overview +******** + +This sample demonstrates the usage of ANS by acting as a peripheral periodically sending +notifications to the connected remote device. + +Requirements +************ + +* A board with Bluetooth LE support +* Smartphone with Bluetooth LE app (ADI Attach, nRF Connect, etc.) or dedicated Bluetooth LE sniffer + +Building and Running +******************** + +To start receiving alerts over the connection, refer to +`GATT Specification Supplement `_ +section 3.12 for byte array to enable/disable notifications and control the service. + +See :zephyr:code-sample-category:`bluetooth` samples for details. diff --git a/samples/bluetooth/peripheral_ans/prj.conf b/samples/bluetooth/peripheral_ans/prj.conf new file mode 100644 index 000000000000..3778ea08025b --- /dev/null +++ b/samples/bluetooth/peripheral_ans/prj.conf @@ -0,0 +1,9 @@ +CONFIG_LOG=y +CONFIG_UTF8=y +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_HCI_ERR_TO_STR=y +CONFIG_BT_DEVICE_NAME="Zephyr Peripheral ANS Sample" +CONFIG_BT_ANS=y +CONFIG_BT_ANS_LOG_LEVEL_DBG=y +CONFIG_BT_ANS_NALRT_CAT_SIMPLE_ALERT=y diff --git a/samples/bluetooth/peripheral_ans/sample.yaml b/samples/bluetooth/peripheral_ans/sample.yaml new file mode 100644 index 000000000000..e8ceff732c48 --- /dev/null +++ b/samples/bluetooth/peripheral_ans/sample.yaml @@ -0,0 +1,15 @@ +sample: + name: Bluetooth Peripheral ANS + description: Demonstrates the Alert Notification Service (ANS) +tests: + sample.bluetooth.peripheral_ans: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf52840dk/nrf52840 + integration_platforms: + - qemu_cortex_m3 + - qemu_x86 + - nrf52840dk/nrf52840 + tags: bluetooth diff --git a/samples/bluetooth/peripheral_ans/src/main.c b/samples/bluetooth/peripheral_ans/src/main.c new file mode 100644 index 000000000000..9e76ef612072 --- /dev/null +++ b/samples/bluetooth/peripheral_ans/src/main.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2025 Sean Kyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(peripheral_ans, CONFIG_LOG_DEFAULT_LEVEL); + +/* + * Sample loops forever, incrementing number of new and unread notifications. Number of new and + * unread notifications will overflow and loop back around. + */ +static uint8_t num_unread; +static uint8_t num_new; + +static const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_ANS_VAL))}; + +static const struct bt_data sd[] = { + BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), +}; + +static void connected(struct bt_conn *conn, uint8_t err) +{ + if (err != 0) { + LOG_ERR("Connection failed, err 0x%02x %s", err, bt_hci_err_to_str(err)); + return; + } + + LOG_INF("Connected"); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + LOG_INF("Disconnected, reason 0x%02x %s", reason, bt_hci_err_to_str(reason)); +} + +static void start_adv(void) +{ + int err; + + err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + if (err != 0) { + LOG_ERR("Advertising failed to start (err %d)", err); + return; + } + + LOG_INF("Advertising successfully started"); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .recycled = start_adv, +}; + +int main(void) +{ + int ret; + + LOG_INF("Sample - Bluetooth Peripheral ANS"); + + ret = bt_enable(NULL); + if (ret != 0) { + LOG_ERR("Failed to enable bluetooth: %d", ret); + return ret; + } + + start_adv(); + + num_unread = 0; + num_new = 0; + + /* At runtime, enable support for given categories */ + uint16_t new_alert_mask = (1 << BT_ANS_CAT_SIMPLE_ALERT) | (1 << BT_ANS_CAT_HIGH_PRI_ALERT); + uint16_t unread_mask = 1 << BT_ANS_CAT_SIMPLE_ALERT; + + ret = bt_ans_set_new_alert_support_category(new_alert_mask); + if (ret != 0) { + LOG_ERR("Unable to set new alert support category mask! (err: %d)", ret); + } + + ret = bt_ans_set_unread_support_category(unread_mask); + if (ret != 0) { + LOG_ERR("Unable to set unread support category mask! (err: %d)", ret); + } + + while (true) { + static const char test_msg[] = "Test Alert!"; + static const char high_pri_msg[] = "Prio Alert!"; + + num_new++; + + ret = bt_ans_notify_new_alert(NULL, BT_ANS_CAT_SIMPLE_ALERT, num_new, test_msg); + if (ret != 0) { + LOG_ERR("Failed to push new alert! (err: %d)", ret); + } + k_sleep(K_SECONDS(1)); + + ret = bt_ans_notify_new_alert(NULL, BT_ANS_CAT_HIGH_PRI_ALERT, num_new, + high_pri_msg); + if (ret != 0) { + LOG_ERR("Failed to push new alert! (err: %d)", ret); + } + k_sleep(K_SECONDS(1)); + + ret = bt_ans_set_unread_count(NULL, BT_ANS_CAT_SIMPLE_ALERT, num_unread); + if (ret != 0) { + LOG_ERR("Failed to push new unread count! (err: %d)", ret); + } + + num_unread++; + + k_sleep(K_SECONDS(5)); + } + + return 0; +} diff --git a/samples/boards/nordic/clock_control/configs/cpuapp_hsfll.overlay b/samples/boards/nordic/clock_control/configs/cpuapp_hsfll.overlay index 0d46dfbda451..f2ab83533f48 100644 --- a/samples/boards/nordic/clock_control/configs/cpuapp_hsfll.overlay +++ b/samples/boards/nordic/clock_control/configs/cpuapp_hsfll.overlay @@ -9,3 +9,7 @@ sample-clock = &cpuapp_hsfll; }; }; + +&cpuapp_hsfll { + status = "okay"; +}; diff --git a/samples/boards/nordic/clock_control/configs/fll16m.overlay b/samples/boards/nordic/clock_control/configs/fll16m.overlay index e6484259ce4f..c4e24588f227 100644 --- a/samples/boards/nordic/clock_control/configs/fll16m.overlay +++ b/samples/boards/nordic/clock_control/configs/fll16m.overlay @@ -9,3 +9,7 @@ sample-clock = &fll16m; }; }; + +&fll16m { + status = "okay"; +}; diff --git a/samples/boards/nordic/clock_control/configs/global_hsfll.overlay b/samples/boards/nordic/clock_control/configs/global_hsfll.overlay index c7e67b9c4e85..ef14d521a589 100644 --- a/samples/boards/nordic/clock_control/configs/global_hsfll.overlay +++ b/samples/boards/nordic/clock_control/configs/global_hsfll.overlay @@ -9,3 +9,7 @@ sample-clock = &hsfll120; }; }; + +&hsfll120 { + status = "okay"; +}; diff --git a/samples/boards/nordic/clock_control/configs/lfclk.overlay b/samples/boards/nordic/clock_control/configs/lfclk.overlay index db48e5f7705d..4b601f56fd08 100644 --- a/samples/boards/nordic/clock_control/configs/lfclk.overlay +++ b/samples/boards/nordic/clock_control/configs/lfclk.overlay @@ -9,3 +9,7 @@ sample-clock = &lfclk; }; }; + +&lfclk { + status = "okay"; +}; diff --git a/samples/boards/nordic/clock_control/configs/uart135.overlay b/samples/boards/nordic/clock_control/configs/uart135.overlay index 547145fa91de..dfc32c3cd9f1 100644 --- a/samples/boards/nordic/clock_control/configs/uart135.overlay +++ b/samples/boards/nordic/clock_control/configs/uart135.overlay @@ -14,3 +14,7 @@ status = "okay"; memory-regions = <&cpuapp_dma_region>; }; + +&fll16m { + status = "okay"; +}; diff --git a/samples/boards/nordic/coresight_stm/prj.conf b/samples/boards/nordic/coresight_stm/prj.conf index 1e935e973c76..9ee7cf8cc03a 100644 --- a/samples/boards/nordic/coresight_stm/prj.conf +++ b/samples/boards/nordic/coresight_stm/prj.conf @@ -1 +1,2 @@ CONFIG_LOG=y +CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y diff --git a/samples/boards/nordic/coresight_stm/pytest/test_stm.py b/samples/boards/nordic/coresight_stm/pytest/test_stm.py index 4af24fbfa3c9..993df0b55fb8 100644 --- a/samples/boards/nordic/coresight_stm/pytest/test_stm.py +++ b/samples/boards/nordic/coresight_stm/pytest/test_stm.py @@ -20,7 +20,7 @@ SB_CONFIG_APP_CPUFLPR_RUN = None # See definition of stm_m_id[] and stm_m_name[] in -# https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/misc/coresight/nrf_etr.c +# https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/debug/debug_nrf_etr.c STM_M_ID = { "sec": 33, "app": 34, @@ -275,9 +275,9 @@ def test_STM_decoded(dut: DeviceAdapter): app_constraints = STMLimits( # all values in us - log_0_arg=1.8, - log_1_arg=2.1, - log_2_arg=2.0, + log_0_arg=0.6, + log_1_arg=0.6, + log_2_arg=2.1, log_3_arg=2.1, log_str=4.5, tracepoint=0.5, @@ -286,35 +286,35 @@ def test_STM_decoded(dut: DeviceAdapter): ) rad_constraints = STMLimits( # all values in us - log_0_arg=4.6, - log_1_arg=5.0, - log_2_arg=5.2, - log_3_arg=5.6, - log_str=6.3, + log_0_arg=5.6, + log_1_arg=5.8, + log_2_arg=6.1, + log_3_arg=6.4, + log_str=7.1, tracepoint=0.5, tracepoint_d32=0.5, tolerance=0.5, ) ppr_constraints = STMLimits( # all values in us - log_0_arg=25.7, - log_1_arg=27.1, - log_2_arg=27.3, - log_3_arg=30.4, - log_str=65.7, + log_0_arg=2.3, + log_1_arg=2.0, + log_2_arg=26.9, + log_3_arg=27.5, + log_str=68.3, tracepoint=0.55, tracepoint_d32=0.25, tolerance=0.5, ) flpr_constraints = STMLimits( # all values in us - log_0_arg=1.3, - log_1_arg=1.6, - log_2_arg=1.6, - log_3_arg=1.7, + log_0_arg=0.2, + log_1_arg=0.2, + log_2_arg=1.2, + log_3_arg=1.2, log_str=3.0, - tracepoint=0.5, - tracepoint_d32=0.5, + tracepoint=0.25, + tracepoint_d32=0.25, tolerance=0.5, ) diff --git a/samples/boards/nordic/coresight_stm/sample.yaml b/samples/boards/nordic/coresight_stm/sample.yaml index 000241d4d979..9ff835d8ffad 100644 --- a/samples/boards/nordic/coresight_stm/sample.yaml +++ b/samples/boards/nordic/coresight_stm/sample.yaml @@ -22,6 +22,13 @@ tests: - SB_CONFIG_APP_CPUPPR_RUN=y - SB_CONFIG_APP_CPUFLPR_RUN=y + sample.boards.nrf.coresight_stm.tpiu.dict: + required_snippets: + - nordic-log-stm-tpiu-dict + extra_args: + - SB_CONFIG_APP_CPUPPR_RUN=y + - SB_CONFIG_APP_CPUFLPR_RUN=y + sample.boards.nrf.coresight_stm: harness: pytest harness_config: diff --git a/samples/boards/nordic/mesh/onoff-app/prj.conf b/samples/boards/nordic/mesh/onoff-app/prj.conf index 0e67042b2653..0783579e795e 100644 --- a/samples/boards/nordic/mesh/onoff-app/prj.conf +++ b/samples/boards/nordic/mesh/onoff-app/prj.conf @@ -9,7 +9,7 @@ CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y CONFIG_BT_MESH_RPL_STORE_TIMEOUT=600 diff --git a/samples/boards/nordic/mesh/onoff-app/src/main.c b/samples/boards/nordic/mesh/onoff-app/src/main.c index 17b04c87fad6..a90c45fe7f09 100644 --- a/samples/boards/nordic/mesh/onoff-app/src/main.c +++ b/samples/boards/nordic/mesh/onoff-app/src/main.c @@ -47,6 +47,7 @@ #include #include #include +#include /* Model Operation Codes */ #define BT_MESH_MODEL_OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01) @@ -366,9 +367,13 @@ static int gen_onoff_status(const struct bt_mesh_model *model, return 0; } -static int output_number(bt_mesh_output_action_t action, uint32_t number) +static int output_numeric(bt_mesh_output_action_t action, uint8_t *numeric, size_t size) { - printk("OOB Number %06u\n", number); + uint64_t number = 0ull; + + sys_get_le(&number, numeric, size); + + printk("OOB Number %06" PRIu64 "\n", number); return 0; } @@ -525,7 +530,7 @@ static const struct bt_mesh_prov prov = { #if 1 .output_size = 6, .output_actions = (BT_MESH_DISPLAY_NUMBER | BT_MESH_DISPLAY_STRING), - .output_number = output_number, + .output_numeric = output_numeric, .output_string = output_string, #else .output_size = 0, diff --git a/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/prj.conf b/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/prj.conf index 3bb984208c70..96b5466b4a16 100644 --- a/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/prj.conf +++ b/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/prj.conf @@ -7,7 +7,7 @@ CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y CONFIG_BT_OBSERVER=y CONFIG_BT_BROADCASTER=y diff --git a/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/src/mesh/ble_mesh.c b/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/src/mesh/ble_mesh.c index 0234d8d971be..c55e0d0ab77e 100644 --- a/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/src/mesh/ble_mesh.c +++ b/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/src/mesh/ble_mesh.c @@ -10,9 +10,13 @@ #ifdef OOB_AUTH_ENABLE -static int output_number(bt_mesh_output_action_t action, uint32_t number) +static int output_numeric(bt_mesh_output_action_t action, uint8_t *numeric, size_t size) { - printk("OOB Number: %u\n", number); + uint64_t number = 0ull; + + sys_get_le(&number, numeric, size); + + printk("OOB Number %06" PRIu64 "\n", number); return 0; } @@ -42,7 +46,7 @@ static const struct bt_mesh_prov prov = { .output_size = 6, .output_actions = BT_MESH_DISPLAY_NUMBER | BT_MESH_DISPLAY_STRING, - .output_number = output_number, + .output_numeric = output_numeric, .output_string = output_string, #endif diff --git a/samples/boards/nordic/nrf53_sync_rtc/sysbuild.conf b/samples/boards/nordic/nrf53_sync_rtc/sysbuild.conf new file mode 100644 index 000000000000..6408669a8474 --- /dev/null +++ b/samples/boards/nordic/nrf53_sync_rtc/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/boards/nordic/nrf_ironside/update/src/main.c b/samples/boards/nordic/nrf_ironside/update/src/main.c index 29d058ca139c..ee8823217de2 100644 --- a/samples/boards/nordic/nrf_ironside/update/src/main.c +++ b/samples/boards/nordic/nrf_ironside/update/src/main.c @@ -10,6 +10,9 @@ LOG_MODULE_REGISTER(app, LOG_LEVEL_INF); +BUILD_ASSERT(CONFIG_UPDATE_BLOB_ADDRESS >= IRONSIDE_UPDATE_MIN_ADDRESS); +BUILD_ASSERT(CONFIG_UPDATE_BLOB_ADDRESS <= IRONSIDE_UPDATE_MAX_ADDRESS); + int main(void) { int err; diff --git a/samples/boards/nordic/spis_wakeup/Kconfig.sysbuild b/samples/boards/nordic/spis_wakeup/Kconfig.sysbuild new file mode 100644 index 000000000000..caf02cc11919 --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/Kconfig.sysbuild @@ -0,0 +1,22 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "$(ZEPHYR_BASE)/share/sysbuild/Kconfig" + +choice REMOTE_NRF54H20_CORE + prompt "Remote nRF54h20 core" + default REMOTE_NRF54H20_CPURAD_CORE + depends on SOC_NRF54H20_CPUAPP + +config REMOTE_NRF54H20_CPUPPR_CORE + bool "ppr core" + +config REMOTE_NRF54H20_CPURAD_CORE + bool "cpurad" + +endchoice + +config REMOTE_BOARD + string + default "$(BOARD)/nrf54h20/cpurad" if SOC_NRF54H20_CPUAPP && REMOTE_NRF54H20_CPURAD_CORE + default "$(BOARD)/nrf54h20/cpuppr/xip" if SOC_NRF54H20_CPUAPP && REMOTE_NRF54H20_CPUPPR_CORE diff --git a/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_common.dtsi b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 000000000000..7ce17ba9bd1a --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + led = &led0; + spis = &spi130; + /delete-property/ sw0; + /delete-property/ sw1; + /delete-property/ sw2; + /delete-property/ sw3; + /delete-property/ mcuboot-led0; + /delete-property/ mcuboot-button0; + }; + /delete-node/ buttons; +}; + +&exmif { + status = "disabled"; +}; + +&gpiote130 { + status = "okay"; + owned-channels = <0>; +}; + +&pinctrl { + spi130_default_alt: spi130_default_alt { + group1 { + psels = , + , + , + ; + }; + }; + + spi130_sleep_alt: spi130_sleep_alt { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; +}; + +&spi130 { + compatible = "nordic,nrf-spis"; + status = "okay"; + def-char = <0x00>; + pinctrl-0 = <&spi130_default_alt>; + pinctrl-1 = <&spi130_sleep_alt>; + pinctrl-names = "default", "sleep"; + wake-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; + memory-regions = <&cpuapp_dma_region>; + /delete-property/ rx-delay-supported; + /delete-property/ rx-delay; +}; diff --git a/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index ae3c8b6c81fc..75d90b40595a 100644 --- a/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -3,64 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "nrf54h20dk_nrf54h20_common.dtsi" + +/* LED1 will be used by the cpurad core. */ / { aliases { - led = &led0; - spis = &spi130; /delete-property/ led1; - /delete-property/ sw0; - /delete-property/ sw1; - /delete-property/ sw2; - /delete-property/ sw3; }; - /delete-node/ buttons; }; /delete-node/ &led1; - -&exmif { - status = "disabled"; -}; - -&gpiote130 { - status = "okay"; - owned-channels = <0>; -}; - -&pinctrl { - spi130_default_alt: spi130_default_alt { - group1 { - psels = , - , - , - ; - }; - }; - - spi130_sleep_alt: spi130_sleep_alt { - group1 { - psels = , - , - , - ; - low-power-enable; - }; - }; -}; - -&spi130 { - compatible = "nordic,nrf-spis"; - status = "okay"; - def-char = <0x00>; - pinctrl-0 = <&spi130_default_alt>; - pinctrl-1 = <&spi130_sleep_alt>; - pinctrl-names = "default", "sleep"; - wake-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; - memory-regions = <&cpuapp_dma_region>; - /delete-property/ rx-delay-supported; - /delete-property/ rx-delay; -}; - -&uart136 { - zephyr,pm-device-runtime-auto; -}; diff --git a/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp_with_cpuppr.overlay b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp_with_cpuppr.overlay new file mode 100644 index 000000000000..fc0f24ad71c0 --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp_with_cpuppr.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&spi131 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; + +&uart135 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; diff --git a/samples/boards/nordic/spis_wakeup/prj.conf b/samples/boards/nordic/spis_wakeup/prj.conf index ca92fc6de6ae..e313ffeed82b 100644 --- a/samples/boards/nordic/spis_wakeup/prj.conf +++ b/samples/boards/nordic/spis_wakeup/prj.conf @@ -3,8 +3,6 @@ CONFIG_SPI_SLAVE=y CONFIG_GPIO=y CONFIG_PM=y -CONFIG_PM_S2RAM=y -CONFIG_PM_S2RAM_CUSTOM_MARKING=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y diff --git a/samples/boards/nordic/spis_wakeup/sample.yaml b/samples/boards/nordic/spis_wakeup/sample.yaml index 7bc97eedcb99..a2dca27d3e82 100644 --- a/samples/boards/nordic/spis_wakeup/sample.yaml +++ b/samples/boards/nordic/spis_wakeup/sample.yaml @@ -1,22 +1,32 @@ common: sysbuild: true depends_on: spi + tags: + - spi + harness: console + harness_config: + fixture: spi_loopback + type: multi_line + ordered: true + regex: + - ".*SPIS: waiting for SPI transfer" + - ".*SPIS: woken up by" sample: name: SPI wakeup sample tests: sample.drivers.spis.wakeup: - tags: - - spi platform_allow: - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp - harness: console - harness_config: - fixture: spi_loopback - type: multi_line - ordered: true - regex: - - ".*SPIS: waiting for SPI transfer" - - ".*SPIS: woken up by" + sample.drivers.spis.wakeup.ppr: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + - SB_CONFIG_REMOTE_NRF54H20_CPUPPR_CORE=y + - spis_wakeup_CONFIG_SOC_NRF54H20_CPURAD_ENABLE=n + - spis_wakeup_SNIPPET=nordic-ppr-xip + - DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpuapp_with_cpuppr.overlay" diff --git a/samples/boards/nordic/spis_wakeup/sysbuild.cmake b/samples/boards/nordic/spis_wakeup/sysbuild.cmake index bbd350fbe637..becedfd6971f 100644 --- a/samples/boards/nordic/spis_wakeup/sysbuild.cmake +++ b/samples/boards/nordic/spis_wakeup/sysbuild.cmake @@ -3,12 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 # -if(SB_CONFIG_SOC_NRF54H20) +if(SB_CONFIG_REMOTE_BOARD) # Add remote project ExternalZephyrProject_Add( APPLICATION wakeup_trigger SOURCE_DIR ${APP_DIR}/wakeup_trigger - BOARD ${SB_CONFIG_BOARD}/${SB_CONFIG_SOC}/cpurad + BOARD ${SB_CONFIG_REMOTE_BOARD} BOARD_REVISION ${BOARD_REVISION} ) endif() diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_common.dtsi b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 000000000000..7ebf62fdae49 --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + led = &led1; + }; + + leds { + compatible = "gpio-leds"; + + led1: led_1 { + gpios = <&gpio9 1 GPIO_ACTIVE_HIGH>; + label = "Green LED 1"; + }; + }; +}; + +&gpiote130 { + status = "okay"; + owned-channels = <1>; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio9 { + status = "okay"; +}; + +&pinctrl { + spi131_default_alt: spi131_default_alt { + group1 { + psels = , + , + ; + }; + }; + + spi131_sleep_alt: spi131_sleep_alt { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +&spi131 { + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi131_default_alt>; + pinctrl-1 = <&spi131_sleep_alt>; + pinctrl-names = "default", "sleep"; + overrun-character = <0x00>; + cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; + wake-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; + + spim_dt: spi-device@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = ; + }; +}; diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf new file mode 100644 index 000000000000..7b0ca9cbcfa3 --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf @@ -0,0 +1 @@ +CONFIG_ASSERT=n diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpuppr_xip.overlay b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpuppr_xip.overlay new file mode 100644 index 000000000000..0e01ff40bb9e --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpuppr_xip.overlay @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.conf b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 000000000000..9eaa8724bb39 --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1,3 @@ +CONFIG_PM=y + +CONFIG_ASSERT=y diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.overlay index c54fb28742e9..846a44d165a3 100644 --- a/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.overlay +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -3,70 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -/ { - aliases { - led = &led1; - }; - - leds { - compatible = "gpio-leds"; - led1: led_1 { - gpios = <&gpio9 1 GPIO_ACTIVE_HIGH>; - label = "Green LED 1"; - }; - }; -}; - -&gpiote130 { - status = "okay"; - owned-channels = <1>; -}; - -&gpio0 { - status = "okay"; -}; - -&gpio9 { - status = "okay"; -}; - -&pinctrl { - spi131_default_alt: spi131_default_alt { - group1 { - psels = , - , - ; - }; - }; - - spi131_sleep_alt: spi131_sleep_alt { - group1 { - psels = , - , - ; - low-power-enable; - }; - }; -}; +#include "nrf54h20dk_nrf54h20_common.dtsi" &spi131 { - compatible = "nordic,nrf-spim"; - status = "okay"; - pinctrl-0 = <&spi131_default_alt>; - pinctrl-1 = <&spi131_sleep_alt>; - pinctrl-names = "default", "sleep"; - overrun-character = <0x00>; - cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; - wake-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; - zephyr,pm-device-runtime-auto; memory-regions = <&cpurad_dma_region>; - spim_dt: spi-device@0 { - compatible = "vnd,spi-device"; - reg = <0>; - spi-max-frequency = ; - }; -}; - -&uart135 { - zephyr,pm-device-runtime-auto; }; diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/prj.conf b/samples/boards/nordic/spis_wakeup/wakeup_trigger/prj.conf index 1de6459a6083..662d75582fea 100644 --- a/samples/boards/nordic/spis_wakeup/wakeup_trigger/prj.conf +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/prj.conf @@ -2,12 +2,7 @@ CONFIG_SPI=y CONFIG_SPI_NRFX_WAKE_TIMEOUT_US=500 CONFIG_GPIO=y -CONFIG_PM=y -CONFIG_PM_S2RAM=y -CONFIG_PM_S2RAM_CUSTOM_MARKING=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_ASSERT=y - CONFIG_LOG=y diff --git a/samples/boards/nordic/system_off/Kconfig b/samples/boards/nordic/system_off/Kconfig index c7b4a9f85575..f5e5ce944acc 100644 --- a/samples/boards/nordic/system_off/Kconfig +++ b/samples/boards/nordic/system_off/Kconfig @@ -23,4 +23,9 @@ config LPCOMP_WAKEUP_ENABLE help Enable system off wakeup from analog comparator. +config SYS_CLOCK_DISABLE + bool "Power down system clock before system off" + help + System clock and GRTC will be switched off during system off. + source "Kconfig.zephyr" diff --git a/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l15_cpuapp_comparator.overlay b/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l15_cpuapp_comparator.overlay index f0b39b456206..ce93cee141a1 100644 --- a/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l15_cpuapp_comparator.overlay +++ b/samples/boards/nordic/system_off/boards/nrf54l15dk_nrf54l15_cpuapp_comparator.overlay @@ -1,6 +1,8 @@ +#include + &comp { compatible = "nordic,nrf-lpcomp"; - psel = "AIN4"; + psel = ; refsel = "VDD_4_8"; status = "okay"; }; diff --git a/samples/boards/nordic/system_off/sample.yaml b/samples/boards/nordic/system_off/sample.yaml index b11f3439e7f6..ce9321a845b3 100644 --- a/samples/boards/nordic/system_off/sample.yaml +++ b/samples/boards/nordic/system_off/sample.yaml @@ -47,6 +47,44 @@ tests: - "Off count: 0" - "Active Ticks:" - "Entering system off; press sw0 to restart" + sample.boards.nrf.system_off.grtc_off: + platform_allow: + - nrf54l15dk/nrf54l05/cpuapp + - nrf54l15dk/nrf54l10/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_configs: + - CONFIG_SYS_CLOCK_DISABLE=y + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "system off demo" + - "Retained data not supported" + - "System clock will be disabled" + - "Entering system off; press sw0 to restart" + sample.boards.nrf.system_off.retained_mem.grtc_off: + platform_allow: + - nrf54l15dk/nrf54l05/cpuapp + - nrf54l15dk/nrf54l10/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_configs: + - CONFIG_APP_USE_RETAINED_MEM=y + - CONFIG_SYS_CLOCK_DISABLE=y + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "system off demo" + - "Retained data: valid" + - "Boot count: 1" + - "Off count: 0" + - "Active Ticks:" + - "System clock will be disabled" + - "Entering system off; press sw0 to restart" sample.boards.nrf.system_off.grtc_wakeup: platform_allow: - nrf54l15dk/nrf54l05/cpuapp diff --git a/samples/boards/nordic/system_off/src/main.c b/samples/boards/nordic/system_off/src/main.c index b4c2eeb2b1bb..020e88a5449e 100644 --- a/samples/boards/nordic/system_off/src/main.c +++ b/samples/boards/nordic/system_off/src/main.c @@ -17,6 +17,7 @@ #include #include #include +#include #define NON_WAKEUP_RESET_REASON (RESET_PIN | RESET_SOFTWARE | RESET_POR | RESET_DEBUG) @@ -97,11 +98,15 @@ int main(void) printf("Retained data not supported\n"); } +#if defined(CONFIG_SYS_CLOCK_DISABLE) + printf("System clock will be disabled\n"); +#endif #if defined(CONFIG_GRTC_WAKEUP_ENABLE) int err = z_nrf_grtc_wakeup_prepare(DEEP_SLEEP_TIME_S * USEC_PER_SEC); if (err < 0) { printk("Unable to prepare GRTC as a wake up source (err = %d).\n", err); + return 0; } else { printk("Entering system off; wait %u seconds to restart\n", DEEP_SLEEP_TIME_S); } @@ -141,6 +146,9 @@ int main(void) } hwinfo_clear_reset_cause(); +#if defined(CONFIG_SYS_CLOCK_DISABLE) + sys_clock_disable(); +#endif sys_poweroff(); return 0; diff --git a/samples/boards/st/power_mgmt/suspend_to_ram/prj.conf b/samples/boards/st/power_mgmt/suspend_to_ram/prj.conf index b9a1cf9305e4..1f23c5a27e2c 100644 --- a/samples/boards/st/power_mgmt/suspend_to_ram/prj.conf +++ b/samples/boards/st/power_mgmt/suspend_to_ram/prj.conf @@ -2,7 +2,6 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y CONFIG_PM_DEVICE_SYSTEM_MANAGED=y -CONFIG_PM_S2RAM=y CONFIG_ADC=y CONFIG_ENTROPY_GENERATOR=y CONFIG_SPI=y diff --git a/samples/drivers/adc/adc_dt/sample.yaml b/samples/drivers/adc/adc_dt/sample.yaml index b6eaa02cf14a..d6842d47f988 100644 --- a/samples/drivers/adc/adc_dt/sample.yaml +++ b/samples/drivers/adc/adc_dt/sample.yaml @@ -16,6 +16,7 @@ tests: - nrf51dk/nrf51822 - nrf52840dk/nrf52840 - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_common.dtsi b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 000000000000..291faa0440de --- /dev/null +++ b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,50 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +/ { + aliases { + adc0 = &adc; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.01 */ + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.02 */ + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P9.01 */ + zephyr,vref-mv = <3686>; /* 3.6V * 1024 */ + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.03 */ + zephyr,input-negative = ; /* P1.07 */ + }; +}; diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index d4f9e8db7c2b..658b19b0ae5d 100644 --- a/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -4,47 +4,4 @@ * Copyright (c) 2024 Nordic Semiconductor ASA */ -/ { - aliases { - adc0 = &adc; - }; -}; - -&adc { - #address-cells = <1>; - #size-cells = <0>; - - channel@0 { - reg = <0>; - zephyr,gain = "ADC_GAIN_1_2"; - zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; - zephyr,input-positive = ; /* P1.01 */ - }; - - channel@1 { - reg = <1>; - zephyr,gain = "ADC_GAIN_1_2"; - zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; - zephyr,input-positive = ; /* P1.02 */ - }; - - channel@2 { - reg = <2>; - zephyr,gain = "ADC_GAIN_1_2"; - zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; - zephyr,input-positive = ; /* P9.01 */ - zephyr,vref-mv = <3686>; /* 3.6V * 1024 */ - }; - - channel@7 { - reg = <7>; - zephyr,gain = "ADC_GAIN_1_2"; - zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; - zephyr,input-positive = ; /* P1.03 */ - zephyr,input-negative = ; /* P1.07 */ - }; -}; +#include "nrf54h20dk_nrf54h20_common.dtsi" diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..bcd359c3aa23 --- /dev/null +++ b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&adc { + status = "okay"; +}; diff --git a/samples/drivers/adc/adc_sequence/sample.yaml b/samples/drivers/adc/adc_sequence/sample.yaml index d176e2593d4b..6927bcdf88d9 100644 --- a/samples/drivers/adc/adc_sequence/sample.yaml +++ b/samples/drivers/adc/adc_sequence/sample.yaml @@ -19,6 +19,7 @@ tests: - cy8cproto_062_4343w - nrf52840dk/nrf52840 - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp @@ -32,6 +33,7 @@ tests: sample.drivers.adc.adc_sequence.8bit: platform_allow: - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: diff --git a/samples/drivers/adc/adc_sequence/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/adc/adc_sequence/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..2570d64e2eb3 --- /dev/null +++ b/samples/drivers/adc/adc_sequence/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "../../../boards/nrf54h20dk_nrf54h20_common.dtsi" + +&adc { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; diff --git a/samples/drivers/adc/adc_sequence/sysbuild/vpr_launcher/prj.conf b/samples/drivers/adc/adc_sequence/sysbuild/vpr_launcher/prj.conf new file mode 100644 index 000000000000..b2a4ba591044 --- /dev/null +++ b/samples/drivers/adc/adc_sequence/sysbuild/vpr_launcher/prj.conf @@ -0,0 +1 @@ +# nothing here diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.conf b/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.conf new file mode 100644 index 000000000000..7dfef7da2839 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256 diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..f31ea5090df8 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * SDA = P2.8 and P2.9 + * SCL = P1.2 and P1.3 + */ + +/ { + aliases { + i2c-controller = &i2c130; + i2c-controller-target = &i2c131; + }; +}; + +&pinctrl { + i2c130_default: i2c130_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c130_sleep: i2c130_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c131_default: i2c131_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c131_sleep: i2c131_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c130 { + clock-frequency = ; + pinctrl-0 = <&i2c130_default>; + pinctrl-1 = <&i2c130_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + status = "okay"; +}; + +&i2c131 { + compatible = "nordic,nrf-twis"; + clock-frequency = ; + pinctrl-0 = <&i2c131_default>; + pinctrl-1 = <&i2c131_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; +}; diff --git a/samples/drivers/i2c/rtio_loopback/sample.yaml b/samples/drivers/i2c/rtio_loopback/sample.yaml index a356a2697fdd..dadfe1fff98e 100644 --- a/samples/drivers/i2c/rtio_loopback/sample.yaml +++ b/samples/drivers/i2c/rtio_loopback/sample.yaml @@ -15,6 +15,7 @@ tests: - b_u585i_iot02a - nrf5340dk/nrf5340/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - nucleo_f401re diff --git a/samples/drivers/i2c/rtio_loopback/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/i2c/rtio_loopback/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..69aedabd69dc --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c130 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; + +&i2c131 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; diff --git a/samples/drivers/i2c/rtio_loopback/sysbuild/vpr_launcher/prj.conf b/samples/drivers/i2c/rtio_loopback/sysbuild/vpr_launcher/prj.conf new file mode 100644 index 000000000000..d6c8f934808e --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/sysbuild/vpr_launcher/prj.conf @@ -0,0 +1,3 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# nothing here diff --git a/samples/drivers/jesd216/sample.yaml b/samples/drivers/jesd216/sample.yaml index a5b661c492ce..4fd0af6c9ca2 100644 --- a/samples/drivers/jesd216/sample.yaml +++ b/samples/drivers/jesd216/sample.yaml @@ -30,8 +30,11 @@ tests: platform_allow: nrf52840dk/nrf52840 integration_platforms: - nrf52840dk/nrf52840 - sample.drivers.jesd216.nrf54lm20: + sample.drivers.jesd216.nrf54l: platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l10/cpuapp + - nrf54l15dk/nrf54l05/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf54lm20dk/nrf54lm20a/cpuapp diff --git a/samples/drivers/mbox/sysbuild.conf b/samples/drivers/mbox/sysbuild.conf new file mode 100644 index 000000000000..6408669a8474 --- /dev/null +++ b/samples/drivers/mbox/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/drivers/spi_bitbang/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/samples/drivers/spi_bitbang/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..d3083d6cbd94 --- /dev/null +++ b/samples/drivers/spi_bitbang/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Test requires loopback between P0.06 and P0.07. + * No other driver on SPI_CLK and SPI_CS. + */ + +/ { + spibb0: spibb0 { + compatible = "zephyr,spi-bitbang"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + clk-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + }; +}; + +&gpio0 { + status = "okay"; +}; + +&gpiote130 { + status = "okay"; + owned-channels = <7>; +}; diff --git a/samples/drivers/spi_bitbang/sample.yaml b/samples/drivers/spi_bitbang/sample.yaml index c90f02313f2b..e3265ce2fdb6 100644 --- a/samples/drivers/spi_bitbang/sample.yaml +++ b/samples/drivers/spi_bitbang/sample.yaml @@ -9,6 +9,7 @@ tests: platform_allow: - nrf52840dk/nrf52840 - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: diff --git a/samples/drivers/watchdog/sample.yaml b/samples/drivers/watchdog/sample.yaml index a1069108fb05..8cf1d7db91a5 100644 --- a/samples/drivers/watchdog/sample.yaml +++ b/samples/drivers/watchdog/sample.yaml @@ -26,6 +26,7 @@ tests: - panb611evb/nrf54l15/cpuapp/ns - panb611evb/nrf54l15/cpuflpr - panb611evb/nrf54l15/cpuflpr/xip + - nrf54lm20dk/nrf54lm20a/cpuapp/ns - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54l15dk/nrf54l10/cpuapp/ns - bl54l15_dvk/nrf54l10/cpuapp/ns diff --git a/samples/net/dns_resolve/Kconfig.sysbuild b/samples/net/dns_resolve/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/dns_resolve/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/ipv4_autoconf/Kconfig.sysbuild b/samples/net/ipv4_autoconf/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/ipv4_autoconf/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/lwm2m_client/Kconfig.sysbuild b/samples/net/lwm2m_client/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/lwm2m_client/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/lwm2m_client/overlay-nrf91x.conf b/samples/net/lwm2m_client/overlay-nrf91x.conf new file mode 100644 index 000000000000..7b902178e078 --- /dev/null +++ b/samples/net/lwm2m_client/overlay-nrf91x.conf @@ -0,0 +1,53 @@ +# Configuration file for nRF91x +# This file is merged with prj.conf in the application folder, and options +# set here will take precedence if they are present in both files. + +# General +CONFIG_MAIN_STACK_SIZE=4096 + +CONFIG_NET_SOCKETS=y +CONFIG_NET_NATIVE=y +CONFIG_NET_SOCKETS_OFFLOAD=y + +CONFIG_NET_CONFIG_MY_IPV6_ADDR="" +CONFIG_NET_CONFIG_PEER_IPV6_ADDR="" +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_CONFIG_MY_IPV4_GW="" + +CONFIG_NET_CONFIG_NEED_IPV6=n +CONFIG_NET_CONFIG_NEED_IPV4=n +CONFIG_NET_CONFIG_AUTO_INIT=n + +# Modem related configurations +CONFIG_NRF_MODEM_LIB_NET_IF=y +CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_DOWN=n +CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_CONNECT=n +CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_START=n +CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC=y + +CONFIG_LTE_LINK_CONTROL_LOG_LEVEL_DBG=n +CONFIG_NRF_MODEM_LIB_NET_IF_LOG_LEVEL_DBG=n + +# Disable Duplicate Address Detection (DAD) +# due to not being properly implemented for offloaded interfaces. +CONFIG_NET_IPV6_NBR_CACHE=n +CONFIG_NET_IPV6_MLD=n + +# Zephyr NET Connection Manager and Connectivity layer. +CONFIG_NET_CONNECTION_MANAGER=y +CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024 + +CONFIG_NET_SAMPLE_LWM2M_ID="nrf91x" +CONFIG_NET_SAMPLE_LWM2M_SERVER="coaps://leshan.eclipseprojects.io:5684" +CONFIG_LWM2M_DNS_SUPPORT=y + +## Enable DTLS support +CONFIG_LWM2M_DTLS_SUPPORT=y +CONFIG_LWM2M_TLS_SESSION_CACHING=y +CONFIG_LWM2M_DTLS_CID=y +CONFIG_TLS_CREDENTIALS=y + +## Crypto +CONFIG_OBERON_BACKEND=y +CONFIG_NORDIC_SECURITY_BACKEND=y +CONFIG_MBEDTLS_SHA256_C=y diff --git a/samples/net/mdns_responder/Kconfig.sysbuild b/samples/net/mdns_responder/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/mdns_responder/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/mqtt_publisher/Kconfig.sysbuild b/samples/net/mqtt_publisher/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/mqtt_publisher/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/mqtt_sn_publisher/Kconfig.sysbuild b/samples/net/mqtt_sn_publisher/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/mqtt_sn_publisher/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/big_http_download/prj.conf b/samples/net/sockets/big_http_download/prj.conf index a406f314dfb2..8677e7113e4b 100644 --- a/samples/net/sockets/big_http_download/prj.conf +++ b/samples/net/sockets/big_http_download/prj.conf @@ -3,6 +3,7 @@ CONFIG_REQUIRES_FULL_LIBC=y CONFIG_MBEDTLS=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_MD=y +CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y CONFIG_MAIN_STACK_SIZE=2536 # Networking config diff --git a/samples/net/sockets/coap_server/Kconfig.sysbuild b/samples/net/sockets/coap_server/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/sockets/coap_server/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/echo_async/Kconfig.sysbuild b/samples/net/sockets/echo_async/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/sockets/echo_async/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/echo_client/Kconfig.sysbuild b/samples/net/sockets/echo_client/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/sockets/echo_client/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/echo_server/Kconfig.sysbuild b/samples/net/sockets/echo_server/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/sockets/echo_server/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/http_get/Kconfig.sysbuild b/samples/net/sockets/http_get/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/sockets/http_get/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/http_server/Kconfig b/samples/net/sockets/http_server/Kconfig index 2f607259dfaa..07d5b26e52d5 100644 --- a/samples/net/sockets/http_server/Kconfig +++ b/samples/net/sockets/http_server/Kconfig @@ -17,7 +17,7 @@ config NET_SAMPLE_HTTP_SERVER_SERVICE_PORT config NET_SAMPLE_HTTPS_SERVICE bool "Enable https service" depends on NET_SOCKETS_SOCKOPT_TLS || TLS_CREDENTIALS - imply MBEDTLS_PSA_CRYPTO_C if !BUILD_WITH_TFM + select PSA_CRYPTO if NET_SAMPLE_HTTPS_SERVICE diff --git a/samples/net/sockets/sntp_client/Kconfig.sysbuild b/samples/net/sockets/sntp_client/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/sockets/sntp_client/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/syslog_net/Kconfig.sysbuild b/samples/net/syslog_net/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/syslog_net/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/telnet/Kconfig.sysbuild b/samples/net/telnet/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/telnet/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/wifi/Kconfig.sysbuild b/samples/net/wifi/Kconfig.sysbuild new file mode 100644 index 000000000000..158551060c56 --- /dev/null +++ b/samples/net/wifi/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/wifi/shell/sample.yaml b/samples/net/wifi/shell/sample.yaml index 5f72e0686116..8543e6bfb38b 100644 --- a/samples/net/wifi/shell/sample.yaml +++ b/samples/net/wifi/shell/sample.yaml @@ -58,6 +58,7 @@ tests: - nrf7002dk/nrf5340/cpuapp/nrf7001 sample.net.wifi.nrf7002ek: extra_args: + - SB_CONFIG_WIFI_NRF70=y - CONFIG_BUILD_ONLY_NO_BLOBS=y - SHIELD=nrf7002ek platform_allow: @@ -69,6 +70,7 @@ tests: sample.net.wifi.nrf7002eb: extra_args: - CONFIG_NRF70_UTIL=y + - SB_CONFIG_WIFI_NRF70=y - CONFIG_BUILD_ONLY_NO_BLOBS=y - SHIELD=nrf7002eb platform_allow: diff --git a/samples/subsys/ipc/ipc_service/icmsg/sysbuild.conf b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.conf new file mode 100644 index 000000000000..6408669a8474 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.conf b/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.conf new file mode 100644 index 000000000000..6408669a8474 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.conf b/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.conf new file mode 100644 index 000000000000..6408669a8474 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/logging/multidomain/sysbuild.conf b/samples/subsys/logging/multidomain/sysbuild.conf new file mode 100644 index 000000000000..6408669a8474 --- /dev/null +++ b/samples/subsys/logging/multidomain/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf new file mode 100644 index 000000000000..98260877332f --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf @@ -0,0 +1,10 @@ +# +# Copyright (c) 2022 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT_MAX_CONN=2 +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=502 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 diff --git a/samples/subsys/mgmt/updatehub/overlay-psa.conf b/samples/subsys/mgmt/updatehub/overlay-psa.conf index 4b5dcfd9af67..8a70becc92d3 100644 --- a/samples/subsys/mgmt/updatehub/overlay-psa.conf +++ b/samples/subsys/mgmt/updatehub/overlay-psa.conf @@ -1,3 +1,2 @@ CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA=y -CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_CRYPTO=y diff --git a/samples/subsys/usb/dfu/sysbuild.conf b/samples/subsys/usb/dfu/sysbuild.conf new file mode 100644 index 000000000000..47f00ff3cff8 --- /dev/null +++ b/samples/subsys/usb/dfu/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/samples/subsys/usb/hid-keyboard/sample.yaml b/samples/subsys/usb/hid-keyboard/sample.yaml index f53ae514f97c..2998f84807d2 100644 --- a/samples/subsys/usb/hid-keyboard/sample.yaml +++ b/samples/subsys/usb/hid-keyboard/sample.yaml @@ -33,3 +33,5 @@ tests: sample.usbd.hid-keyboard.large-out-report: extra_args: - EXTRA_DTC_OVERLAY_FILE="large_out_report.overlay" + extra_configs: + - CONFIG_USBD_HID_SET_POLLING_PERIOD=y diff --git a/samples/subsys/usb/hid-keyboard/src/main.c b/samples/subsys/usb/hid-keyboard/src/main.c index 45580c95a845..39ce8836ff6a 100644 --- a/samples/subsys/usb/hid-keyboard/src/main.c +++ b/samples/subsys/usb/hid-keyboard/src/main.c @@ -206,6 +206,18 @@ int main(void) return ret; } + if (IS_ENABLED(CONFIG_USBD_HID_SET_POLLING_PERIOD)) { + ret = hid_device_set_in_polling(hid_dev, 1000); + if (ret) { + LOG_WRN("Failed to set IN report polling period, %d", ret); + } + + ret = hid_device_set_out_polling(hid_dev, 1000); + if (ret != 0 && ret != -ENOTSUP) { + LOG_WRN("Failed to set OUT report polling period, %d", ret); + } + } + sample_usbd = sample_usbd_init_device(msg_cb); if (sample_usbd == NULL) { LOG_ERR("Failed to initialize USB device"); diff --git a/samples/subsys/usb/uac2_explicit_feedback/app.overlay b/samples/subsys/usb/uac2_explicit_feedback/app.overlay index 3ff71797aa99..21119a79206d 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/app.overlay +++ b/samples/subsys/usb/uac2_explicit_feedback/app.overlay @@ -11,6 +11,7 @@ compatible = "zephyr,uac2"; status = "okay"; full-speed; + high-speed; audio-function = ; uac_aclk: aclk { diff --git a/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf index 0e35fa1f491e..d7526fc6ec9a 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -2,7 +2,3 @@ CONFIG_NRFX_GPPI=y CONFIG_NRFX_TIMER131=y CONFIG_NRFX_GPIOTE130=y - -# Sample is Full-Speed only, prevent High-Speed enumeration -CONFIG_UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED=n -CONFIG_USBD_MAX_SPEED_FULL=y diff --git a/samples/subsys/usb/uac2_explicit_feedback/src/feedback.h b/samples/subsys/usb/uac2_explicit_feedback/src/feedback.h index 7f5bf2027d8f..37c1dc975e58 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/src/feedback.h +++ b/samples/subsys/usb/uac2_explicit_feedback/src/feedback.h @@ -9,15 +9,14 @@ #include -/* Nominal number of samples received on each SOF. This sample is currently - * supporting only 48 kHz sample rate. - */ -#define SAMPLES_PER_SOF 48 +/* This sample is currently supporting only 48 kHz sample rate. */ +#define SAMPLE_RATE 48000 struct feedback_ctx *feedback_init(void); -void feedback_reset_ctx(struct feedback_ctx *ctx); +void feedback_reset_ctx(struct feedback_ctx *ctx, bool microframes); void feedback_process(struct feedback_ctx *ctx); -void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued); +void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued, + bool microframes); uint32_t feedback_value(struct feedback_ctx *ctx); - +#define SAMPLES_PER_SOF 48 #endif /* FEEDBACK_H_ */ diff --git a/samples/subsys/usb/uac2_explicit_feedback/src/feedback_dummy.c b/samples/subsys/usb/uac2_explicit_feedback/src/feedback_dummy.c index 7e274ca2ed05..378a43e06ef4 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/src/feedback_dummy.c +++ b/samples/subsys/usb/uac2_explicit_feedback/src/feedback_dummy.c @@ -5,15 +5,23 @@ */ #include +#include #include "feedback.h" #warning "No target specific feedback code, overruns/underruns will occur" -#define FEEDBACK_K 10 +#define FEEDBACK_FS_K 10 +#define FEEDBACK_FS_SHIFT 4 +#define FEEDBACK_HS_K 13 +#define FEEDBACK_HS_SHIFT 3 + +static struct feedback_ctx { + bool high_speed; +} fb_ctx; struct feedback_ctx *feedback_init(void) { - return NULL; + return &fb_ctx; } void feedback_process(struct feedback_ctx *ctx) @@ -21,19 +29,25 @@ void feedback_process(struct feedback_ctx *ctx) ARG_UNUSED(ctx); } -void feedback_reset_ctx(struct feedback_ctx *ctx) +void feedback_reset_ctx(struct feedback_ctx *ctx, bool microframes) { - ARG_UNUSED(ctx); + ctx->high_speed = microframes; } -void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued) +void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued, + bool microframes) { - ARG_UNUSED(ctx); ARG_UNUSED(i2s_blocks_queued); + + ctx->high_speed = microframes; } uint32_t feedback_value(struct feedback_ctx *ctx) { /* Always request nominal number of samples */ - return SAMPLES_PER_SOF << FEEDBACK_K; + if (USBD_SUPPORTS_HIGH_SPEED && ctx->high_speed) { + return (SAMPLE_RATE / 8000) << (FEEDBACK_HS_K + FEEDBACK_HS_SHIFT); + } + + return (SAMPLE_RATE / 1000) << (FEEDBACK_FS_K + FEEDBACK_FS_SHIFT); } diff --git a/samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf.c b/samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf.c index 62a7ad05ef9c..6b7ed239b268 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf.c +++ b/samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf.c @@ -84,8 +84,14 @@ static const nrfx_timer_t feedback_timer_instance = * Full-Speed isochronous feedback is Q10.10 unsigned integer left-justified in * the 24-bits so it has Q10.14 format. This sample application puts zeroes to * the 4 least significant bits (does not use the bits for extra precision). + * + * High-Speed isochronous feedback is Q12.13 unsigned integer aligned in the + * 32-bits so the binary point is located between second and third byte so it + * has Q16.16 format. This sample applications puts zeroes to the 3 least + * significant bits (does not use the bits for extra precision). */ -#define FEEDBACK_K 10 +#define FEEDBACK_FS_K 10 +#define FEEDBACK_HS_K 13 #if defined(CONFIG_APP_USE_I2S_LRCLK_EDGES_COUNTER) #define FEEDBACK_P 1 #else @@ -93,11 +99,14 @@ static const nrfx_timer_t feedback_timer_instance = #endif #define FEEDBACK_FS_SHIFT 4 +#define FEEDBACK_HS_SHIFT 3 static struct feedback_ctx { uint32_t fb_value; int32_t rel_sof_offset; int32_t base_sof_offset; + uint32_t counts_per_sof; + bool high_speed; union { /* For edge counting */ struct { @@ -190,7 +199,7 @@ struct feedback_ctx *feedback_init(void) feedback_target_init(); - feedback_reset_ctx(&fb_ctx); + feedback_reset_ctx(&fb_ctx, false); if (IS_ENABLED(CONFIG_APP_USE_I2S_LRCLK_EDGES_COUNTER)) { err = feedback_edge_counter_setup(); @@ -239,13 +248,31 @@ struct feedback_ctx *feedback_init(void) return &fb_ctx; } +static uint32_t nominal_feedback_value(struct feedback_ctx *ctx) +{ + if (ctx->high_speed) { + return (SAMPLE_RATE / 8000) << (FEEDBACK_HS_K + FEEDBACK_HS_SHIFT); + } + + return (SAMPLE_RATE / 1000) << (FEEDBACK_FS_K + FEEDBACK_FS_SHIFT); +} + +static uint32_t feedback_period(struct feedback_ctx *ctx) +{ + if (ctx->high_speed) { + return BIT(FEEDBACK_HS_K - FEEDBACK_P); + } + + return BIT(FEEDBACK_FS_K - FEEDBACK_P); +} + static void update_sof_offset(struct feedback_ctx *ctx, uint32_t sof_cc, uint32_t framestart_cc) { int sof_offset; if (!IS_ENABLED(CONFIG_APP_USE_I2S_LRCLK_EDGES_COUNTER)) { - uint32_t clks_per_edge; + uint32_t nominator; /* Convert timer clock (independent from both Audio clock and * USB host SOF clock) to fake sample clock shifted by P values. @@ -255,18 +282,17 @@ static void update_sof_offset(struct feedback_ctx *ctx, uint32_t sof_cc, * when regulated and therefore the relative clock frequency * discrepancies are essentially negligible. */ - clks_per_edge = sof_cc / (SAMPLES_PER_SOF << FEEDBACK_P); - sof_cc /= MAX(clks_per_edge, 1); - framestart_cc /= MAX(clks_per_edge, 1); + nominator = MIN(sof_cc, framestart_cc) * ctx->counts_per_sof; + sof_offset = nominator / MAX(sof_cc, 1); + } else { + sof_offset = framestart_cc; } /* /2 because we treat the middle as a turning point from being * "too late" to "too early". */ - if (framestart_cc > (SAMPLES_PER_SOF << FEEDBACK_P)/2) { - sof_offset = framestart_cc - (SAMPLES_PER_SOF << FEEDBACK_P); - } else { - sof_offset = framestart_cc; + if (sof_offset > ctx->counts_per_sof/2) { + sof_offset -= ctx->counts_per_sof; } /* The heuristic above is not enough when the offset gets too large. @@ -279,17 +305,17 @@ static void update_sof_offset(struct feedback_ctx *ctx, uint32_t sof_cc, if (sof_offset >= 0) { abs_diff = sof_offset - ctx->rel_sof_offset; - base_change = -(SAMPLES_PER_SOF << FEEDBACK_P); + base_change = -ctx->counts_per_sof; } else { abs_diff = ctx->rel_sof_offset - sof_offset; - base_change = SAMPLES_PER_SOF << FEEDBACK_P; + base_change = ctx->counts_per_sof; } /* Adjust base offset only if the change happened through the * outer bound. The actual changes should be significantly lower * than the threshold here. */ - if (abs_diff > (SAMPLES_PER_SOF << FEEDBACK_P)/2) { + if (abs_diff > ctx->counts_per_sof/2) { ctx->base_sof_offset += base_change; } } @@ -297,8 +323,12 @@ static void update_sof_offset(struct feedback_ctx *ctx, uint32_t sof_cc, ctx->rel_sof_offset = sof_offset; } -static inline int32_t offset_to_correction(int32_t offset) +static inline int32_t offset_to_correction(struct feedback_ctx *ctx, int32_t offset) { + if (ctx->high_speed) { + return -(offset / BIT(FEEDBACK_P)) * BIT(FEEDBACK_HS_SHIFT); + } + return -(offset / BIT(FEEDBACK_P)) * BIT(FEEDBACK_FS_SHIFT); } @@ -320,39 +350,66 @@ static int32_t pi_update(struct feedback_ctx *ctx) int32_t error = SP - PV; /* - * With above normalization at Full-Speed, when data received during - * SOF n appears on I2S during SOF n+3, the Ziegler Nichols Ultimate - * Gain is around 1.15 and the oscillation period is around 90 SOF. - * (much nicer oscillations with 204.8 SOF period can be observed with - * gain 0.5 when the delay is not n+3, but n+33 - surprisingly the - * resulting PI coefficients after power of two rounding are the same). + * With above normalization, when data received during SOF n appears on + * I2S during SOF n+3, the Ziegler Nichols Ultimate Gain and oscillation + * periods are as follows: * - * Ziegler-Nichols rule with applied stability margin of 2 results in: - * Kc = 0.22 * Ku = 0.22 * 1.15 = 0.253 - * Ti = 0.83 * tu = 0.83 * 80 = 66.4 + * Full-Speed Linux: Ku = 1.34 tu=77 [FS SOFs] + * Full-Speed Mac OS: Ku = 0.173 tu=580 [FS SOFs] + * High-Speed Mac OS: Ku = 0.895 tu=4516 [HS SOFs] + * High-Speed Windows: Ku = 0.515 tu=819 [HS SOFs] * - * Converting the rules above to parallel PI gives: - * Kp = Kc = 0.253 - * Ki = Kc/Ti = 0.254/66.4 ~= 0.0038253 + * Linux and Mac OS oscillations were very neat, while Windows seems to + * be averaging feedback value and therefore it is hard to get steady + * oscillations without getting buffer uderrun. * - * Because we want fixed-point optimized non-tunable implementation, - * the parameters can be conveniently expressed with power of two: - * Kp ~= pow(2, -2) = 0.25 (divide by 4) - * Ki ~= pow(2, -8) = 0.0039 (divide by 256) + * Ziegler-Nichols rule with applied stability margin of 2 results in: + * [FS Linux] [FS Mac] [HS Mac] [HS Windows] + * Kc = 0.22 * Ku 0.2948 0.0381 0.1969 0.1133 + * Ti = 0.83 * tu 63.91 481.4 3748 647.9 * - * This can be implemented as: + * Converting the rules to work with following simple regulator: * ctx->integrator += error; - * return (error + (ctx->integrator / 64)) / 4; - * but unfortunately such regulator is pretty aggressive and keeps - * oscillating rather quickly around the setpoint (within +-1 sample). + * return (error + (ctx->integrator / Ti)) / invKc; + * + * gives following parameters: + * [FS Linux] [FS Mac] [HS Mac] [HS Windows] + * invKc = 1/Kc 3 26 5 8 + * Ti 64 482 3748 648 + * + * The respective regulators seem to give quarter-amplitude-damping on + * respective hosts, but tuning from one host can get into oscillations + * on another host. The regulation goal is to achieve a single set of + * parameters to be used with all hosts, the only parameter difference + * can be based on operating speed. + * + * After a number of tests with all the hosts, following parameters + * were determined to result in nice no-overshoot response: + * [Full-Speed] [High-Speed] + * invKc 128 128 + * Ti 2048 16384 + * + * The power-of-two parameters were arbitrarily chosen for rounding. + * The 16384 = 2048 * 8 can be considered as unifying integration time. * - * Manually tweaking the constants so the regulator output is shifted - * down by 4 bits (i.e. change /64 to /2048 and /4 to /128) yields - * really good results (the outcome is similar, even slightly better, - * than using I2S LRCLK edge counting directly). + * While the no-overshoot is also present with invKc as low as 32, such + * regulator is pretty aggressive and keeps oscillating rather quickly + * around the setpoint (within +-1 sample). Lowering the controller gain + * (increasing invKc value) yields really good results (the outcome is + * similar to using I2S LRCLK edge counting directly). + * + * The most challenging scenario is for the regulator to stabilize right + * after startup when I2S consumes data faster than nominal sample rate + * (48 kHz = 6 samples per SOF at High-Speed, 48 samples at Full-Speed) + * according to host (I2S consuming data slower slower than nominal + * sample rate is not problematic at all because buffer overrun does not + * stop I2S streaming). This regulator should be able to stabilize for + * any frequency that is within required USB SOF accuracy of 500 ppm, + * i.e. when nominal sample rate is 48 kHz the real sample rate can be + * anywhere in [47.976 kHz; 48.024 kHz] range. */ ctx->integrator += error; - return (error + (ctx->integrator / 2048)) / 128; + return (error + (ctx->integrator / (ctx->high_speed ? 16384 : 2048))) / 128; } void feedback_process(struct feedback_ctx *ctx) @@ -374,17 +431,21 @@ void feedback_process(struct feedback_ctx *ctx) ctx->fb_counter += sof_cc; ctx->fb_periods++; - if (ctx->fb_periods == BIT(FEEDBACK_K - FEEDBACK_P)) { + if (ctx->fb_periods == feedback_period(ctx)) { - /* fb_counter holds Q10.10 value, left-justify it */ - fb = ctx->fb_counter << FEEDBACK_FS_SHIFT; + if (ctx->high_speed) { + fb = ctx->fb_counter << FEEDBACK_HS_SHIFT; + } else { + /* fb_counter holds Q10.10 value, left-justify it */ + fb = ctx->fb_counter << FEEDBACK_FS_SHIFT; + } /* Align I2S FRAMESTART to USB SOF by adjusting reported * feedback value. This is endpoint specific correction * mentioned but not specified in USB 2.0 Specification. */ if (abs(offset) > BIT(FEEDBACK_P)) { - fb += offset_to_correction(offset); + fb += offset_to_correction(ctx, offset); } ctx->fb_value = fb; @@ -392,22 +453,25 @@ void feedback_process(struct feedback_ctx *ctx) ctx->fb_periods = 0; } } else { + const uint32_t zero_lsb_mask = ctx->high_speed ? 0x7 : 0xF; + /* Use PI controller to generate required feedback deviation * from nominal feedback value. */ - fb = SAMPLES_PER_SOF << (FEEDBACK_K + FEEDBACK_FS_SHIFT); + fb = nominal_feedback_value(ctx); /* Clear the additional LSB bits in feedback value, i.e. do not * use the optional extra resolution. */ - fb += pi_update(ctx) & ~0xF; + fb += pi_update(ctx) & ~zero_lsb_mask; ctx->fb_value = fb; } } -void feedback_reset_ctx(struct feedback_ctx *ctx) +void feedback_reset_ctx(struct feedback_ctx *ctx, bool microframes) { /* Reset feedback to nominal value */ - ctx->fb_value = SAMPLES_PER_SOF << (FEEDBACK_K + FEEDBACK_FS_SHIFT); + ctx->high_speed = microframes; + ctx->fb_value = nominal_feedback_value(ctx); if (IS_ENABLED(CONFIG_APP_USE_I2S_LRCLK_EDGES_COUNTER)) { ctx->fb_counter = 0; ctx->fb_periods = 0; @@ -416,19 +480,28 @@ void feedback_reset_ctx(struct feedback_ctx *ctx) } } -void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued) +void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued, + bool microframes) { + ctx->high_speed = microframes; + ctx->fb_value = nominal_feedback_value(ctx); + + if (microframes) { + ctx->counts_per_sof = (SAMPLE_RATE / 8000) << FEEDBACK_P; + } else { + ctx->counts_per_sof = (SAMPLE_RATE / 1000) << FEEDBACK_P; + } + /* I2S data was supposed to go out at SOF, but it is inevitably * delayed due to triggering I2S start by software. Set relative * SOF offset value in a way that ensures that values past "half * frame" are treated as "too late" instead of "too early" */ - ctx->rel_sof_offset = (SAMPLES_PER_SOF << FEEDBACK_P) / 2; + ctx->rel_sof_offset = ctx->counts_per_sof / 2; /* If there are more than 2 I2S blocks queued, use feedback regulator * to correct the situation. */ - ctx->base_sof_offset = (i2s_blocks_queued - 2) * - (SAMPLES_PER_SOF << FEEDBACK_P); + ctx->base_sof_offset = (i2s_blocks_queued - 2) * ctx->counts_per_sof; } uint32_t feedback_value(struct feedback_ctx *ctx) diff --git a/samples/subsys/usb/uac2_explicit_feedback/src/main.c b/samples/subsys/usb/uac2_explicit_feedback/src/main.c index 3f4f596f35c2..40df3f5b8fc7 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/src/main.c +++ b/samples/subsys/usb/uac2_explicit_feedback/src/main.c @@ -20,14 +20,17 @@ LOG_MODULE_REGISTER(uac2_sample, LOG_LEVEL_INF); #define HEADPHONES_OUT_TERMINAL_ID UAC2_ENTITY_ID(DT_NODELABEL(out_terminal)) -#define SAMPLE_FREQUENCY (SAMPLES_PER_SOF * 1000) +#define FS_SAMPLES_PER_SOF 48 +#define HS_SAMPLES_PER_SOF 6 +#define MAX_SAMPLES_PER_SOF MAX(FS_SAMPLES_PER_SOF, HS_SAMPLES_PER_SOF) +#define SAMPLE_FREQUENCY (FS_SAMPLES_PER_SOF * 1000) #define SAMPLE_BIT_WIDTH 16 #define NUMBER_OF_CHANNELS 2 #define BYTES_PER_SAMPLE DIV_ROUND_UP(SAMPLE_BIT_WIDTH, 8) #define BYTES_PER_SLOT (BYTES_PER_SAMPLE * NUMBER_OF_CHANNELS) -#define MIN_BLOCK_SIZE ((SAMPLES_PER_SOF - 1) * BYTES_PER_SLOT) -#define BLOCK_SIZE (SAMPLES_PER_SOF * BYTES_PER_SLOT) -#define MAX_BLOCK_SIZE ((SAMPLES_PER_SOF + 1) * BYTES_PER_SLOT) +#define MIN_BLOCK_SIZE ((MAX_SAMPLES_PER_SOF - 1) * BYTES_PER_SLOT) +#define BLOCK_SIZE (MAX_SAMPLES_PER_SOF * BYTES_PER_SLOT) +#define MAX_BLOCK_SIZE ((MAX_SAMPLES_PER_SOF + 1) * BYTES_PER_SLOT) /* Absolute minimum is 5 buffers (1 actively consumed by I2S, 2nd queued as next * buffer, 3rd acquired by USB stack to receive data to, and 2 to handle SOF/I2S @@ -42,6 +45,7 @@ struct usb_i2s_ctx { const struct device *i2s_dev; bool terminal_enabled; bool i2s_started; + bool microframes; /* Number of blocks written, used to determine when to start I2S. * Overflows are not a problem becuse this variable is not necessary * after I2S is started. @@ -60,15 +64,15 @@ static void uac2_terminal_update_cb(const struct device *dev, uint8_t terminal, * ignore the terminal variable. */ __ASSERT_NO_MSG(terminal == HEADPHONES_OUT_TERMINAL_ID); - /* This sample is for Full-Speed only devices. */ - __ASSERT_NO_MSG(microframes == false); + + ctx->microframes = microframes; ctx->terminal_enabled = enabled; if (ctx->i2s_started && !enabled) { i2s_trigger(ctx->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DROP); ctx->i2s_started = false; ctx->i2s_blocks_written = 0; - feedback_reset_ctx(ctx->fb); + feedback_reset_ctx(ctx->fb, ctx->microframes); } } @@ -114,7 +118,11 @@ static void uac2_data_recv_cb(const struct device *dev, uint8_t terminal, * either disable terminal (or the cable will be disconnected) * which will stop I2S. */ - size = BLOCK_SIZE; + if (USBD_SUPPORTS_HIGH_SPEED && ctx->microframes) { + size = HS_SAMPLES_PER_SOF * BYTES_PER_SLOT; + } else { + size = FS_SAMPLES_PER_SOF * BYTES_PER_SLOT; + } memset(buf, 0, size); } @@ -124,7 +132,7 @@ static void uac2_data_recv_cb(const struct device *dev, uint8_t terminal, if (ret < 0) { ctx->i2s_started = false; ctx->i2s_blocks_written = 0; - feedback_reset_ctx(ctx->fb); + feedback_reset_ctx(ctx->fb, ctx->microframes); /* Most likely underrun occurred, prepare I2S restart */ i2s_trigger(ctx->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_PREPARE); @@ -236,7 +244,7 @@ static void uac2_sof(const struct device *dev, void *user_data) ctx->i2s_blocks_written >= 2) { i2s_trigger(ctx->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_START); ctx->i2s_started = true; - feedback_start(ctx->fb, ctx->i2s_blocks_written); + feedback_start(ctx->fb, ctx->i2s_blocks_written, ctx->microframes); } } diff --git a/samples/subsys/usb/uac2_implicit_feedback/app.overlay b/samples/subsys/usb/uac2_implicit_feedback/app.overlay index 799d9e40d433..583b1f8ef7b3 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/app.overlay +++ b/samples/subsys/usb/uac2_implicit_feedback/app.overlay @@ -11,6 +11,7 @@ compatible = "zephyr,uac2"; status = "okay"; full-speed; + high-speed; audio-function = ; uac_aclk: aclk { diff --git a/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf index 1b1edb40666c..c4e23e5d54fe 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -1,7 +1,3 @@ # Enable timer for asynchronous feedback CONFIG_NRFX_GPPI=y CONFIG_NRFX_TIMER131=y - -# Sample is Full-Speed only, prevent High-Speed enumeration -CONFIG_UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED=n -CONFIG_USBD_MAX_SPEED_FULL=y diff --git a/samples/subsys/usb/uac2_implicit_feedback/src/feedback.h b/samples/subsys/usb/uac2_implicit_feedback/src/feedback.h index 3fff2425d8b8..584bc0135c2c 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/src/feedback.h +++ b/samples/subsys/usb/uac2_implicit_feedback/src/feedback.h @@ -9,15 +9,14 @@ #include -/* Nominal number of samples received on each SOF. This sample is currently - * supporting only 48 kHz sample rate. - */ -#define SAMPLES_PER_SOF 48 +/* This sample is currently supporting only 48 kHz sample rate. */ +#define SAMPLE_RATE 48000 struct feedback_ctx *feedback_init(void); void feedback_reset_ctx(struct feedback_ctx *ctx); void feedback_process(struct feedback_ctx *ctx); -void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued); +void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued, + bool microframes); /* Return offset between I2S block start and USB SOF in samples. * diff --git a/samples/subsys/usb/uac2_implicit_feedback/src/feedback_dummy.c b/samples/subsys/usb/uac2_implicit_feedback/src/feedback_dummy.c index 3b91deafe5c1..d28181033b94 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/src/feedback_dummy.c +++ b/samples/subsys/usb/uac2_implicit_feedback/src/feedback_dummy.c @@ -24,10 +24,12 @@ void feedback_reset_ctx(struct feedback_ctx *ctx) ARG_UNUSED(ctx); } -void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued) +void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued, + bool microframes) { ARG_UNUSED(ctx); ARG_UNUSED(i2s_blocks_queued); + ARG_UNUSED(microframes); } int feedback_samples_offset(struct feedback_ctx *ctx) diff --git a/samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf.c b/samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf.c index a7dfad370b87..9623f22e5662 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf.c +++ b/samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf.c @@ -68,11 +68,12 @@ static const nrfx_timer_t feedback_timer_instance = * SOF offset is around 0 when regulated and therefore the relative clock * frequency discrepancies are essentially negligible. */ -#define CLKS_PER_SAMPLE (16000000 / (SAMPLES_PER_SOF * 1000)) +#define CLKS_PER_SAMPLE (16000000 / (SAMPLE_RATE)) static struct feedback_ctx { int32_t rel_sof_offset; int32_t base_sof_offset; + unsigned int nominal; } fb_ctx; struct feedback_ctx *feedback_init(void) @@ -143,8 +144,8 @@ static void update_sof_offset(struct feedback_ctx *ctx, uint32_t sof_cc, /* /2 because we treat the middle as a turning point from being * "too late" to "too early". */ - if (framestart_cc > (SAMPLES_PER_SOF * CLKS_PER_SAMPLE)/2) { - sof_offset = framestart_cc - SAMPLES_PER_SOF * CLKS_PER_SAMPLE; + if (framestart_cc > (ctx->nominal * CLKS_PER_SAMPLE)/2) { + sof_offset = framestart_cc - ctx->nominal * CLKS_PER_SAMPLE; } else { sof_offset = framestart_cc; } @@ -159,17 +160,17 @@ static void update_sof_offset(struct feedback_ctx *ctx, uint32_t sof_cc, if (sof_offset >= 0) { abs_diff = sof_offset - ctx->rel_sof_offset; - base_change = -(SAMPLES_PER_SOF * CLKS_PER_SAMPLE); + base_change = -(ctx->nominal * CLKS_PER_SAMPLE); } else { abs_diff = ctx->rel_sof_offset - sof_offset; - base_change = SAMPLES_PER_SOF * CLKS_PER_SAMPLE; + base_change = ctx->nominal * CLKS_PER_SAMPLE; } /* Adjust base offset only if the change happened through the * outer bound. The actual changes should be significantly lower * than the threshold here. */ - if (abs_diff > (SAMPLES_PER_SOF * CLKS_PER_SAMPLE)/2) { + if (abs_diff > (ctx->nominal * CLKS_PER_SAMPLE)/2) { ctx->base_sof_offset += base_change; } } @@ -195,19 +196,26 @@ void feedback_reset_ctx(struct feedback_ctx *ctx) ARG_UNUSED(ctx); } -void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued) +void feedback_start(struct feedback_ctx *ctx, int i2s_blocks_queued, + bool microframes) { + if (microframes) { + ctx->nominal = SAMPLE_RATE / 8000; + } else { + ctx->nominal = SAMPLE_RATE / 1000; + } + /* I2S data was supposed to go out at SOF, but it is inevitably * delayed due to triggering I2S start by software. Set relative * SOF offset value in a way that ensures that values past "half * frame" are treated as "too late" instead of "too early" */ - ctx->rel_sof_offset = (SAMPLES_PER_SOF * CLKS_PER_SAMPLE) / 2; + ctx->rel_sof_offset = (ctx->nominal * CLKS_PER_SAMPLE) / 2; /* If there are more than 2 I2S TX blocks queued, use feedback regulator * to correct the situation. */ ctx->base_sof_offset = (i2s_blocks_queued - 2) * - (SAMPLES_PER_SOF * CLKS_PER_SAMPLE); + (ctx->nominal * CLKS_PER_SAMPLE); } int feedback_samples_offset(struct feedback_ctx *ctx) diff --git a/samples/subsys/usb/uac2_implicit_feedback/src/main.c b/samples/subsys/usb/uac2_implicit_feedback/src/main.c index 12abdf4fe681..06334866e7a2 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/src/main.c +++ b/samples/subsys/usb/uac2_implicit_feedback/src/main.c @@ -21,15 +21,17 @@ LOG_MODULE_REGISTER(uac2_sample, LOG_LEVEL_INF); #define HEADPHONES_OUT_TERMINAL_ID UAC2_ENTITY_ID(DT_NODELABEL(out_terminal)) #define MICROPHONE_IN_TERMINAL_ID UAC2_ENTITY_ID(DT_NODELABEL(in_terminal)) -#define SAMPLES_PER_SOF 48 -#define SAMPLE_FREQUENCY (SAMPLES_PER_SOF * 1000) +#define FS_SAMPLES_PER_SOF 48 +#define HS_SAMPLES_PER_SOF 6 +#define MAX_SAMPLES_PER_SOF MAX(FS_SAMPLES_PER_SOF, HS_SAMPLES_PER_SOF) +#define SAMPLE_FREQUENCY (FS_SAMPLES_PER_SOF * 1000) #define SAMPLE_BIT_WIDTH 16 #define NUMBER_OF_CHANNELS 2 #define BYTES_PER_SAMPLE DIV_ROUND_UP(SAMPLE_BIT_WIDTH, 8) #define BYTES_PER_SLOT (BYTES_PER_SAMPLE * NUMBER_OF_CHANNELS) -#define MIN_BLOCK_SIZE ((SAMPLES_PER_SOF - 1) * BYTES_PER_SLOT) -#define BLOCK_SIZE (SAMPLES_PER_SOF * BYTES_PER_SLOT) -#define MAX_BLOCK_SIZE ((SAMPLES_PER_SOF + 1) * BYTES_PER_SLOT) +#define MIN_BLOCK_SIZE ((MAX_SAMPLES_PER_SOF - 1) * BYTES_PER_SLOT) +#define BLOCK_SIZE (MAX_SAMPLES_PER_SOF * BYTES_PER_SLOT) +#define MAX_BLOCK_SIZE ((MAX_SAMPLES_PER_SOF + 1) * BYTES_PER_SLOT) /* Absolute minimum is 5 TX buffers (1 actively consumed by I2S, 2nd queued as * next buffer, 3rd acquired by USB stack to receive data to, and 2 to handle @@ -49,6 +51,7 @@ struct usb_i2s_ctx { bool i2s_started; bool rx_started; bool usb_data_received; + bool microframes; /* Counter used to determine when to start I2S and then when to start * sending RX packets to host. Overflows are not a problem because this * variable is not necessary after both I2S and RX is started. @@ -70,8 +73,8 @@ struct usb_i2s_ctx { * Used to avoid overcompensation in feedback regulator. LSBs indicate * latest write size. */ - uint8_t plus_ones; - uint8_t minus_ones; + uint32_t plus_ones; + uint32_t minus_ones; }; static void uac2_terminal_update_cb(const struct device *dev, uint8_t terminal, @@ -80,8 +83,7 @@ static void uac2_terminal_update_cb(const struct device *dev, uint8_t terminal, { struct usb_i2s_ctx *ctx = user_data; - /* This sample is for Full-Speed only devices. */ - __ASSERT_NO_MSG(microframes == false); + ctx->microframes = microframes; if (terminal == HEADPHONES_OUT_TERMINAL_ID) { ctx->headphones_enabled = enabled; @@ -104,6 +106,15 @@ static void uac2_terminal_update_cb(const struct device *dev, uint8_t terminal, } } +static int nominal_samples_per_sof(struct usb_i2s_ctx *ctx) +{ + if (USBD_SUPPORTS_HIGH_SPEED && ctx->microframes) { + return HS_SAMPLES_PER_SOF; + } + + return FS_SAMPLES_PER_SOF; +} + static void *uac2_get_recv_buf(const struct device *dev, uint8_t terminal, uint16_t size, void *user_data) { @@ -133,6 +144,7 @@ static void uac2_data_recv_cb(const struct device *dev, uint8_t terminal, void *buf, uint16_t size, void *user_data) { struct usb_i2s_ctx *ctx = user_data; + int nominal = nominal_samples_per_sof(ctx); int ret; ctx->usb_data_received = true; @@ -159,11 +171,11 @@ static void uac2_data_recv_cb(const struct device *dev, uint8_t terminal, * of samples sent. */ if (ctx->plus_ones & 1) { - size = (SAMPLES_PER_SOF + 1) * BYTES_PER_SLOT; + size = (nominal + 1) * BYTES_PER_SLOT; } else if (ctx->minus_ones & 1) { - size = (SAMPLES_PER_SOF - 1) * BYTES_PER_SLOT; + size = (nominal - 1) * BYTES_PER_SLOT; } else { - size = SAMPLES_PER_SOF * BYTES_PER_SLOT; + size = nominal * BYTES_PER_SLOT; } memset(buf, 0, size); } @@ -208,6 +220,7 @@ static void uac2_buf_release_cb(const struct device *dev, uint8_t terminal, /* Determine next number of samples to send, called at most once every SOF */ static int next_mic_num_samples(struct usb_i2s_ctx *ctx) { + int nominal = nominal_samples_per_sof(ctx); int offset = feedback_samples_offset(ctx->fb); /* The rolling buffers essentially handle controller dead time, i.e. @@ -217,12 +230,18 @@ static int next_mic_num_samples(struct usb_i2s_ctx *ctx) ctx->plus_ones <<= 1; ctx->minus_ones <<= 1; + /* At Full-Speed only remember last 8 frames */ + if (!USBD_SUPPORTS_HIGH_SPEED || !ctx->microframes) { + ctx->plus_ones &= 0x000000FF; + ctx->minus_ones &= 0x000000FF; + } + if ((offset < 0) && (POPCOUNT(ctx->plus_ones) < -offset)) { /* I2S buffer starts at least 1 sample before SOF, send nominal * + 1 samples to host in order to shift offset towards 0. */ ctx->plus_ones |= 1; - return SAMPLES_PER_SOF + 1; + return nominal + 1; } if ((offset > 0) && (POPCOUNT(ctx->minus_ones) < offset)) { @@ -230,11 +249,11 @@ static int next_mic_num_samples(struct usb_i2s_ctx *ctx) * - 1 samples to host in order to shift offset towards 0 */ ctx->minus_ones |= 1; - return SAMPLES_PER_SOF - 1; + return nominal - 1; } /* I2S is either spot on, or the offset is expected to correct soon */ - return SAMPLES_PER_SOF; + return nominal; } static void process_mic_data(const struct device *dev, struct usb_i2s_ctx *ctx) @@ -488,7 +507,7 @@ static void uac2_sof(const struct device *dev, void *user_data) ctx->i2s_counter >= 2) { i2s_trigger(ctx->i2s_dev, I2S_DIR_BOTH, I2S_TRIGGER_START); ctx->i2s_started = true; - feedback_start(ctx->fb, ctx->i2s_counter); + feedback_start(ctx->fb, ctx->i2s_counter, ctx->microframes); ctx->i2s_counter = 0; } diff --git a/samples/sysbuild/hello_world/sysbuild.cmake b/samples/sysbuild/hello_world/sysbuild.cmake index c7c2615c665a..8f8fc49dbff3 100644 --- a/samples/sysbuild/hello_world/sysbuild.cmake +++ b/samples/sysbuild/hello_world/sysbuild.cmake @@ -11,5 +11,17 @@ ExternalZephyrProject_Add( BOARD ${SB_CONFIG_REMOTE_BOARD} ) +if(SB_CONFIG_SOC_SERIES_NRF53X) + set_property(GLOBAL APPEND PROPERTY PM_DOMAINS CPUNET) + set_property(GLOBAL APPEND PROPERTY PM_CPUNET_IMAGES remote) + set_property(GLOBAL PROPERTY DOMAIN_APP_CPUNET remote) + set(CPUNET_PM_DOMAIN_DYNAMIC_PARTITION remote CACHE INTERNAL "") +else(SB_CONFIG_SOC_SERIES_NRF54LX) + set_property(GLOBAL APPEND PROPERTY PM_DOMAINS CPUFLPR) + set_property(GLOBAL APPEND PROPERTY PM_CPUFLPR_IMAGES remote) + set_property(GLOBAL PROPERTY DOMAIN_APP_CPUFLPR remote) + set(CPUFLPR_PM_DOMAIN_DYNAMIC_PARTITION remote CACHE INTERNAL "") +endif() + add_dependencies(${DEFAULT_IMAGE} remote) sysbuild_add_dependencies(FLASH ${DEFAULT_IMAGE} remote) diff --git a/samples/tfm_integration/config_build/sample.yaml b/samples/tfm_integration/config_build/sample.yaml index 3c46c148f7ba..55c4e2348081 100644 --- a/samples/tfm_integration/config_build/sample.yaml +++ b/samples/tfm_integration/config_build/sample.yaml @@ -10,6 +10,7 @@ common: - nrf9160dk/nrf9160/ns - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54l15dk/nrf54l10/cpuapp/ns + - nrf54lm20dk/nrf54lm20a/cpuapp/ns - bl5340_dvk/nrf5340/cpuapp/ns integration_platforms: - nrf5340dk/nrf5340/cpuapp/ns diff --git a/samples/tfm_integration/psa_crypto/sample.yaml b/samples/tfm_integration/psa_crypto/sample.yaml index ea9844730fc1..7d287985bf3c 100644 --- a/samples/tfm_integration/psa_crypto/sample.yaml +++ b/samples/tfm_integration/psa_crypto/sample.yaml @@ -16,8 +16,6 @@ tests: platform_allow: - mps2/an521/cpu0/ns - v2m_musca_s1/musca_s1/ns - - nrf5340dk/nrf5340/cpuapp/ns - - nrf9160dk/nrf9160/ns - stm32l562e_dk/stm32l562xx/ns - bl5340_dvk/nrf5340/cpuapp/ns - max32657evkit/max32657/ns diff --git a/samples/tfm_integration/tfm_ipc/sample.yaml b/samples/tfm_integration/tfm_ipc/sample.yaml index 390efa24fb7e..154d91b23f31 100644 --- a/samples/tfm_integration/tfm_ipc/sample.yaml +++ b/samples/tfm_integration/tfm_ipc/sample.yaml @@ -35,6 +35,7 @@ tests: - mps2/an521/cpu0/ns - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54l15dk/nrf54l10/cpuapp/ns + - nrf54lm20dk/nrf54lm20a/cpuapp/ns extra_configs: - CONFIG_TFM_BL2=n harness: console diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index a600004aae7a..16aacd4c6a80 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -23,6 +23,8 @@ import unidiff import yaml +from dotenv import load_dotenv + from yamllint import config, linter from junitparser import TestCase, TestSuite, JUnitXml, Skipped, Error, Failure @@ -503,6 +505,22 @@ class KconfigCheck(ComplianceTest): # Kconfig symbol prefix/namespace. CONFIG_ = "CONFIG_" + # If modules should be excluded from checks. + EXCLUDE_MODULES = False + + # This block list contains a list of upstream Zephyr modules that should not be checked + # DO NOT MERGE CHANGES TO THIS WITHOUT BUILD SYSTEM AND CODE OWNER APPROVAL! + external_module_name_block_list = ['canopennode', 'chre', 'cmsis', 'cmsis-dsp', 'cmsis-nn', + 'cmsis_6', 'edtt', 'fatfs', 'hal_st', 'hal_tdk', + 'hal_wurthelektronik', 'liblc3', 'libmetal', 'littlefs', + 'loramac-node', 'lvgl', 'lz4', 'mipi-sys-t', 'nanopb', + 'net-tools', 'nrf_hw_models', 'open-amp', 'percepio', + 'picolibc', 'segger', 'tf-m-tests', 'tinycrypt', + 'uoscore-uedhoc', 'zscilib'] + + # Holds a list or directories/files which should not be checked + blocked_module_dirs = [] + def run(self): kconf = self.parse_kconfig() @@ -540,6 +558,22 @@ def get_modules(self, _module_dirs_file, modules_file, sysbuild_modules_file, se modules = [name for name in os.listdir(modules_dir) if modules_dir / name / 'Kconfig'] + nrf_modules_dir = (Path(ZEPHYR_BASE) / '..' / 'nrf' / 'modules').resolve() + nrf_modules = [] + + for module in modules: + if module in self.external_module_name_block_list: + self.blocked_module_dirs.append(modules_dir / module / 'Kconfig') + + if os.path.exists(nrf_modules_dir): + nrf_modules = [name for name in os.listdir(nrf_modules_dir) if + os.path.exists(os.path.join(nrf_modules_dir, name, + 'Kconfig'))] + + for module in nrf_modules: + if module in self.external_module_name_block_list: + self.blocked_module_dirs.append(nrf_modules_dir / module / 'Kconfig') + with open(modules_file, 'r') as fp_module_file: content = fp_module_file.read() @@ -549,8 +583,32 @@ def get_modules(self, _module_dirs_file, modules_file, sysbuild_modules_file, se re.sub('[^a-zA-Z0-9]', '_', module).upper(), modules_dir / module / 'Kconfig' )) + for module in nrf_modules: + fp_module_file.write("ZEPHYR_{}_KCONFIG = {}\n".format( + re.sub('[^a-zA-Z0-9]', '_', module).upper(), + nrf_modules_dir / module / 'Kconfig' + )) + fp_module_file.write("NCS_{}_KCONFIG = {}\n".format( + re.sub('[^a-zA-Z0-9]', '_', module).upper(), + modules_dir / module / 'Kconfig' + )) + + # Add NRF as static entry as workaround for ext Kconfig root support + fp_module_file.write("ZEPHYR_NRF_KCONFIG = {}\n".format( + nrf_modules_dir / '..' / 'Kconfig.nrf' + )) fp_module_file.write(content) + with open(sysbuild_modules_file, 'r') as fp_sysbuild_module_file: + content = fp_sysbuild_module_file.read() + + with open(sysbuild_modules_file, 'w') as fp_sysbuild_module_file: + # Add NRF as static entry as workaround for ext Kconfig root support + fp_sysbuild_module_file.write("SYSBUILD_NRF_KCONFIG = {}\n".format( + nrf_modules_dir / '..' / 'sysbuild' / 'Kconfig.sysbuild' + )) + fp_sysbuild_module_file.write(content) + def get_kconfig_dts(self, kconfig_dts_file, settings_file): """ Generate the Kconfig.dts using dts/bindings as the source. @@ -700,14 +758,14 @@ def parse_kconfig(self): os.environ["KCONFIG_BINARY_DIR"] = kconfiglib_dir os.environ['DEVICETREE_CONF'] = "dummy" os.environ['TOOLCHAIN_HAS_NEWLIB'] = "y" - os.environ['KCONFIG_ENV_FILE'] = os.path.join(kconfiglib_dir, "kconfig_module_dirs.env") + kconfig_env_file = os.path.join(kconfiglib_dir, "kconfig_module_dirs.env") # Older name for DEVICETREE_CONF, for compatibility with older Zephyr # versions that don't have the renaming os.environ["GENERATED_DTS_BOARD_CONF"] = "dummy" # For multi repo support - self.get_modules(os.environ['KCONFIG_ENV_FILE'], + self.get_modules(kconfig_env_file, os.path.join(kconfiglib_dir, "Kconfig.modules"), os.path.join(kconfiglib_dir, "Kconfig.sysbuild.modules"), os.path.join(kconfiglib_dir, "settings_file.txt")) @@ -721,6 +779,8 @@ def parse_kconfig(self): # symbols within Kconfig files os.environ["KCONFIG_WARN_UNDEF"] = "y" + load_dotenv(kconfig_env_file) + try: # Note this will both print warnings to stderr _and_ return # them: so some warnings might get printed @@ -1018,9 +1078,32 @@ def check_no_enable_in_boolean_prompt(self, kconf): # Checks that boolean's prompt does not start with "Enable...". for node in kconf.node_iter(): - # skip Kconfig nodes not in-tree (will present an absolute path) + skip_node = False + + # skip Kconfig nodes not in-tree when set to (will present an absolute path) if os.path.isabs(node.filename): - continue + if self.EXCLUDE_MODULES is True: + continue + + normalised_file_name = Path(node.filename).resolve() + + for module_name in self.external_module_name_block_list: + # Workaround for being unable to use full_match() due to python version + if '/modules/' in str(normalised_file_name) and \ + ('/' + module_name + '/') in str(normalised_file_name): + skip_node = True + break + + if skip_node: + continue + + for blocked_dir in self.blocked_module_dirs: + if normalised_file_name.match(blocked_dir, case_sensitive=True): + skip_node = True + break + + if skip_node: + continue # 'kconfiglib' is global # pylint: disable=undefined-variable @@ -1146,6 +1229,10 @@ def check_no_undef_outside_kconfig(self, kconf): grep_stdout = git("grep", "--line-number", "-I", "--null", "--perl-regexp", regex, "--", ":!/doc/releases", ":!/doc/security/vulnerabilities.rst", + ":!/doc/nrf/releases_and_maturity", + ":!/doc/nrf/libraries/bin/lwm2m_carrier/CHANGELOG.rst", + ":!/doc/nrf/app_dev/device_guides/nrf70/wifi_advanced_security_modes.rst", + ":!/doc/nrf-bm/release_notes", cwd=GIT_TOP) # splitlines() supports various line terminators @@ -1263,9 +1350,6 @@ def check_no_undef_outside_kconfig(self, kconf): "FOO_LOG_LEVEL", "FOO_SETTING_1", "FOO_SETTING_2", - "GEN_UICR_GENERATE_PERIPHCONF", # Used in specialized build tool, not part of main Kconfig - "GEN_UICR_SECONDARY", # Used in specialized build tool, not part of main Kconfig - "GEN_UICR_SECONDARY_GENERATE_PERIPHCONF", # Used in specialized build tool, not part of main Kconfig "HEAP_MEM_POOL_ADD_SIZE_", # Used as an option matching prefix "HUGETLBFS", # Linux, in boards/xtensa/intel_adsp_cavs25/doc "IAR_BUFFERED_WRITE", @@ -1345,6 +1429,81 @@ def check_no_undef_outside_kconfig(self, kconf): # documentation "ZTEST_FAIL_TEST_", # regex in tests/ztest/fail/CMakeLists.txt # zephyr-keep-sorted-stop + + # NCS-specific allow list + # zephyr-keep-sorted-start re(^\s+") + "APPLICATION", # Example documentation + "BAR", # Example documentation + "BOOT_IMAGE_ACCESS_HOOK", # MCUboot setting used in documentation + "BT_ADV_PROV_", # Documentation + "BT_CTLR_TX_PWR_MINUS", # CHIP documentation + "BT_CTLR_TX_PWR_MINUS_", # CHIP documentation + "BT_CTLR_TX_PWR_PLUS", # CHIP documentation + "BT_CTLR_TX_PWR_PLUS_", # CHIP documentation + "BT_SDC_ADDITIONAL_MEMORY", # From dragoon repo + "CHANNEL", # NRF desktop + "CHANNEL_FETCHED_DATA_MAX_SIZE", # NRF desktop + "CHANNEL_TRANSPORT_DISABLED", # NRF desktop + "CHANNEL_TRANSPORT_IDLE", # NRF desktop + "CHANNEL_TRANSPORT_RSP_READY", # NRF desktop + "CHANNEL_TRANSPORT_WAIT_RSP", # NRF desktop + "CHIP_DFU_OVER_BT_SMP", # CHIP module + "CHIP_LAST_FABRIC_REMOVED_ACTION_DELAY", # CHIP module + "CHIP_LAST_FABRIC_REMOVED_ERASE_AND_PAIRING_START", # CHIP module + "CHIP_LAST_FABRIC_REMOVED_ERASE_AND_REBOOT", # CHIP module + "CHIP_LAST_FABRIC_REMOVED_ERASE_ONLY", # CHIP module + "CHIP_LAST_FABRIC_REMOVED_NONE", # CHIP module + "CHIP_MEMORY_PROFILING", # CHIP module + "CHIP_NUS", # CHIP module + "CHIP_NUS_FIXED_PASSKEY", # CHIP module + "CHIP_NUS_MAX_COMMANDS", # CHIP module + "CHIP_NUS_MAX_COMMAND_LEN", # CHIP module + "CHIP_QSPI_NOR", # CHIP module + "CHIP_SPI_NOR", # CHIP module + "CHIP_WIFI", # CHIP module + "DESKTOP_DVFS_STATE_", # NRF desktop + "DESKTOP_DVFS_STATE_CONFIG_CHANNEL_ENABLE", # NRF desktop + "DESKTOP_DVFS_STATE_INITIALIZING_ENABLE", # NRF desktop + "DESKTOP_DVFS_STATE_LLPM_CONNECTED_ENABLE", # NRF desktop + "DESKTOP_DVFS_STATE_SMP_TRANSFER_ENABLE", # NRF desktop + "DESKTOP_DVFS_STATE_USB_CONNECTED_ENABLE", # NRF desktop + "FACTORY_DATA_CUSTOM_BACKEND", # CHIP module + "MEMFAULT_", # Documentation + "MEMFAULT_NCS", # Documentation + "MEMFAULT_NCS_", # Documentation + "MY_CUSTOM_CONFIG", # Example documentation + "MY_EXT_API_ENABLED", # Example documentation + "MY_EXT_API_REQUIRED", # Example documentation + "NCS_IS_VARIANT_IMAGE", # Build system defined symbol + "NCS_MCUBOOT_UUID_CID_IMAGE_0_VALUE", # MCUboot + "NCS_MCUBOOT_UUID_CID_IMAGE_1_VALUE", # MCUboot + "NCS_VARIANT_MERGE_KCONFIG", # Build system defined symbol + "NRF_MODEM_LIB_TRACE_BACKEND_MY_TRACE_BACKEND", # Documentation + "PM_PARTITION_SIZE", # Used in search link + "PM_PARTITION_SIZE_", # Used in documentation + "PM_PARTITION_SIZE_MEMFAULT_STORAGE", # Created by Kconfig template + "PM_PARTITION_SIZE_SETTINGS", # Created by Kconfig template + "SOC_NRF54H20_CPUSEC", # Internal + "SSF_SERVER_PSA_CRYPTO_SERVICE_ENABLED", # Internal + "STATUS_", # NRF desktop + "STATUS_COUNT", # NRF desktop + "STATUS_DISCONNECTED", # NRF desktop + "STATUS_FETCH", # NRF desktop + "STATUS_GET_BOARD_NAME", # NRF desktop + "STATUS_GET_HWID", # NRF desktop + "STATUS_GET_MAX_MOD_ID", # NRF desktop + "STATUS_GET_PEER", # NRF desktop + "STATUS_GET_PEERS_CACHE", # NRF desktop + "STATUS_INDEX_PEERS", # NRF desktop + "STATUS_LIST", # NRF desktop + "STATUS_PENDING", # NRF desktop + "STATUS_POS", # NRF desktop + "STATUS_REJECT", # NRF desktop + "STATUS_SET", # NRF desktop + "STATUS_SUCCESS", # NRF desktop + "STATUS_TIMEOUT", # NRF desktop + "STATUS_WRITE_FAIL", # NRF desktop + # zephyr-keep-sorted-stop } @@ -1370,6 +1529,7 @@ class KconfigBasicNoModulesCheck(KconfigBasicCheck): name = "KconfigBasicNoModules" path_hint = "" EMPTY_FILE_CONTENTS = "# Empty\n" + EXCLUDE_MODULES = True def get_modules(self, module_dirs_file, modules_file, sysbuild_modules_file, settings_file): with open(module_dirs_file, 'w') as fp_module_file: @@ -1415,6 +1575,32 @@ class SysbuildKconfigCheck(KconfigCheck): "OTHER_APP_IMAGE_PATH", # Used in sysbuild documentation as example "SECOND_SAMPLE", # Used in sysbuild documentation # zephyr-keep-sorted-stop + + # NCS-specific allowlist + # zephyr-keep-sorted-start re(^\s+") + "APP_CPUNET_RUN", # Used by sample + "APP_DFU", # Used by sample + "BT_FAST_PAIR", # Legacy/removed, used in migration documentation + "COMP_DATA_LAYOUT_ARRAY", # Used by test + "COMP_DATA_LAYOUT_MULTIPLE", # Used by test + "COMP_DATA_LAYOUT_SINGLE", # Used by test + "DTM_NO_DFE", # Used by DTM application + "DTM_TRANSPORT_HCI", # Used by DTM application + "FIRMWARE_LOADER_IMAGE_ABC", # Used in documentation + "INCLUDE_REMOTE_IMAGE", # Used by machine learning application + "MCUBOOT_FPROTECT_ALLOW_COMBINED_REGIONS", # Used in migration documentation + "ML_APP_INCLUDE_REMOTE_IMAGE", # Used by machine learning application + "ML_APP_REMOTE_BOARD", # Used by machine learning application + "MY_APP_IMAGE_ABC", # Used in documentation + "NETCORE_ABC", # Used in documentation + "REMOTE_GLOBAL_DOMAIN_CLOCK_FREQUENCY_SWITCHING", # Used in tests + "SOC_FLASH_NRF_RADIO_SYNC_RPC", # Used in documentation + "SUIT_ENVELOPE_", # Used by jinja + "SUIT_ENVELOPE_SEQUENCE_NUM", # Legacy/removed, used in migration documentation + "SUIT_MPI_", # Used by jinja + "SUIT_RECOVERY_APPLICATION_CUSTOM", # Used in documentation + "SUPPORT_NETCORE_PERIPHERAL_RADIO_TEST", # Used by wifi radio test sample + # zephyr-keep-sorted-stop } @@ -1436,6 +1622,7 @@ class SysbuildKconfigBasicNoModulesCheck(SysbuildKconfigCheck, KconfigBasicNoMod """ name = "SysbuildKconfigBasicNoModules" path_hint = "" + EXCLUDE_MODULES = True class Nits(ComplianceTest): @@ -1655,6 +1842,34 @@ def filter_py(root, fnames): mime=True) == "text/x-python")] +class CMakeStyle(ComplianceTest): + """ + Checks cmake style added/modified files + """ + name = "CMakeStyle" + doc = "See https://docs.zephyrproject.org/latest/contribute/style/cmake.html for more details." + + def run(self): + # Loop through added/modified files + for fname in get_files(filter="d"): + if fname.endswith(".cmake") or fname == "CMakeLists.txt": + self.check_style(fname) + + def check_style(self, fname): + SPACE_BEFORE_OPEN_BRACKETS_CHECK = re.compile(r"^\s*if\s+\(") + TAB_INDENTATION_CHECK = re.compile(r"^\t+") + + with open(fname, encoding="utf-8") as f: + for line_num, line in enumerate(f.readlines(), start=1): + if TAB_INDENTATION_CHECK.match(line): + self.fmtd_failure("error", "CMakeStyle", fname, line_num, + "Use spaces instead of tabs for indentation") + + if SPACE_BEFORE_OPEN_BRACKETS_CHECK.match(line): + self.fmtd_failure("error", "CMakeStyle", fname, line_num, + "Remove space before '(' in if() statements") + + class Identity(ComplianceTest): """ Checks if Emails of author and signed-off messages are consistent. diff --git a/scripts/dts/gen_dts_cmake.py b/scripts/dts/gen_dts_cmake.py index 5dd4a8779d32..a8a2c3df611f 100755 --- a/scripts/dts/gen_dts_cmake.py +++ b/scripts/dts/gen_dts_cmake.py @@ -134,10 +134,8 @@ def main(): cmake_prop = f'DT_PROP|{node.path}|{item}' cmake_props.append(f'"{cmake_prop}" "{escape(cmake_value)}"') - if item == 'compatible': - # compatibles is always an array - for comp in node.props[item].val: - compatible2paths[comp].append(node.path) + for comp in node.compats: + compatible2paths[comp].append(node.path) if node.regs is not None: cmake_props.append(f'"DT_REG|{node.path}|NUM" "{len(node.regs)}"') diff --git a/scripts/gitlint/zephyr_commit_rules.py b/scripts/gitlint/zephyr_commit_rules.py index a2c9cd3cb7fe..ef317e22684c 100644 --- a/scripts/gitlint/zephyr_commit_rules.py +++ b/scripts/gitlint/zephyr_commit_rules.py @@ -78,7 +78,7 @@ class TitleMaxLengthRevert(LineRule): name = "title-max-length-no-revert" id = "UC5" target = CommitMessageTitle - options_spec = [IntOption('line-length', 75, "Max line length")] + options_spec = [IntOption('line-length', 120, "Max line length")] violation_message = "Commit title exceeds max length ({0}>{1})" def validate(self, line, _commit): @@ -103,7 +103,7 @@ class MaxLineLengthExceptions(LineRule): name = "max-line-length-with-exceptions" id = "UC4" target = CommitMessageBody - options_spec = [IntOption('line-length', 75, "Max line length")] + options_spec = [IntOption('line-length', 120, "Max line length")] violation_message = "Commit message body line exceeds max length ({0}>{1})" def validate(self, line, _commit): diff --git a/scripts/pylib/twister/twisterlib/hardwaremap.py b/scripts/pylib/twister/twisterlib/hardwaremap.py index 74c384ab5d6e..6deca0ac4adf 100644 --- a/scripts/pylib/twister/twisterlib/hardwaremap.py +++ b/scripts/pylib/twister/twisterlib/hardwaremap.py @@ -386,7 +386,7 @@ def save(self, hwm_file): boot_ids = [] # use existing map - self.detected = natsorted(self.detected, key=lambda x: x.serial or '') + self.detected.sort(key=lambda x: x.serial or '') if os.path.exists(hwm_file): with open(hwm_file) as yaml_file: hwm = yaml.load(yaml_file, Loader=SafeLoader) diff --git a/scripts/quarantine.yaml b/scripts/quarantine.yaml new file mode 100644 index 000000000000..20c4f9248ea9 --- /dev/null +++ b/scripts/quarantine.yaml @@ -0,0 +1,88 @@ +# The configurations resulting as a product of scenarios and platforms +# will be skipped if quarantine is used. More details here: +# https://docs.zephyrproject.org/latest/guides/test/twister.html#quarantine + +- scenarios: + - testing.ztest.busy_sim + - testing.ztest.busy_sim_nrf52840dk_pin + platforms: + - nrf52840dk_nrf52840 + +# Already reported, but will not be fixed (look at the discussion): +# https://github.com/zephyrproject-rtos/zephyr/issues/44947 +- scenarios: + - libraries.cmsis_dsp.matrix.unary_f64 + platforms: + - nrf5340dk_nrf5340_cpunet + - qemu_cortex_m3 + comment: "Flash overflows" + +# Already reported, but will not be fixed (look at the discussion): +# https://github.com/zephyrproject-rtos/zephyr/issues/44947 +- scenarios: + - libraries.cmsis_dsp.matrix.binary_f16 + - libraries.cmsis_dsp.matrix.binary_f16.fpu + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + comment: "Flash overflows" + +# Already reported, but will not be fixed (look at the discussion): +# https://github.com/zephyrproject-rtos/zephyr/issues/44947 +- scenarios: + - libraries.cmsis_dsp.matrix.binary_q15 + - libraries.cmsis_dsp.matrix.binary_q15.fpu + - libraries.cmsis_dsp.matrix.unary_f32 + - libraries.cmsis_dsp.matrix.unary_f32.fpu + - libraries.cmsis_dsp.matrix.unary_f64 + - libraries.cmsis_dsp.matrix.unary_f64.fpu + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + - nrf9160dk_nrf9160_ns + comment: "Flash overflows" + +# libsdl2-dev package should be added into docker image +- scenarios: + - sample.boards.nrf.nrf_led_matrix + - sample.display.lvgl.gui + platforms: + - native_posix + comment: "libsdl2-dev package not available" + +- scenarios: + - sample.net.sockets.echo_server.usbnet + - sample.net.sockets.echo_server.usbnet_composite + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + comment: "Ram/flash overflows, also in the upstream" + +- scenarios: + - sample.net.zperf.netusb_ecm + - sample.net.zperf.netusb_eem + - sample.net.zperf.netusb_rndis + platforms: + - nrf52833dk_nrf52833 + - nrf5340dk_nrf5340_cpuapp_ns + comment: "Ram/flash overflows, also in the upstream" + +- scenarios: + - net.mqtt.tls + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + - nrf9160dk_nrf9160_ns + comment: "Ram/flash overflows, also in the upstream" + +- scenarios: + - kernel.common.picolibc + - libraries.picolibc + - libraries.libc.picolibc.mem_alloc + - libraries.picolibc.sprintf_new + platforms: + - nrf52dk_nrf52832 + comment: "Ram overflows, also in the upstream" + +- scenarios: + - sample.psa_crypto + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + - nrf9160dk_nrf9160_ns + comment: "Due to using sdk-zephyr manifest instead of nrf. Should be fixed after the change" diff --git a/scripts/requirements-actions.in b/scripts/requirements-actions.in index 997afed38712..cc170f59d779 100644 --- a/scripts/requirements-actions.in +++ b/scripts/requirements-actions.in @@ -6,7 +6,7 @@ clang-format>=15.0.0 elasticsearch<9 exceptiongroup>=1.0.0rc8 gcovr==6.0 -gitlint>=0.19.1 +gitlint-core>=0.19.1 gitpython>=3.1.41 ijson intelhex @@ -22,6 +22,7 @@ pykwalify pylint>=3 pyserial pytest +python-dotenv python-magic-bin; sys_platform == "win32" python-magic; sys_platform != "win32" pyyaml diff --git a/scripts/requirements-actions.txt b/scripts/requirements-actions.txt index 8c28b2d22f77..32173378473d 100644 --- a/scripts/requirements-actions.txt +++ b/scripts/requirements-actions.txt @@ -345,14 +345,10 @@ gitdb==4.0.12 \ --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf # via gitpython -gitlint==0.19.1 \ - --hash=sha256:26bb085959148d99fbbc178b4e56fda6c3edd7646b7c2a24d8ee1f8e036ed85d \ - --hash=sha256:b5b70fb894e80849b69abbb65ee7dbb3520fc3511f202a6e6b6ddf1a71ee8f61 - # via -r requirements-actions.in gitlint-core==0.19.1 \ --hash=sha256:7bf977b03ff581624a9e03f65ebb8502cc12dfaa3e92d23e8b2b54bbdaa29992 \ --hash=sha256:f41effd1dcbc06ffbfc56b6888cce72241796f517b46bd9fd4ab1b145056988c - # via gitlint + # via -r requirements-actions.in gitpython==3.1.44 \ --hash=sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110 \ --hash=sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269 @@ -880,6 +876,10 @@ python-debian==1.0.1 \ --hash=sha256:3ada9b83a3d671b58081782c0969cffa0102f6ce433fbbc7cf21275b8b5cc771 \ --hash=sha256:8f137c230c1d9279c2ac892b35915068b2aca090c9fd3da5671ff87af32af12c # via reuse +python-dotenv==1.1.1 \ + --hash=sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc \ + --hash=sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab + # via -r requirements-actions.in python-magic==0.4.27 ; sys_platform != 'win32' \ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 diff --git a/scripts/requirements-build-test.txt b/scripts/requirements-build-test.txt index 2ce1227e3e70..e6264b11ea5e 100644 --- a/scripts/requirements-build-test.txt +++ b/scripts/requirements-build-test.txt @@ -19,3 +19,5 @@ mypy # used for JUnit XML parsing in CTest harness junitparser>=3.0.0 + +python-dotenv diff --git a/scripts/requirements-compliance.txt b/scripts/requirements-compliance.txt index 3c3841cf33ed..dcb8baae0f97 100644 --- a/scripts/requirements-compliance.txt +++ b/scripts/requirements-compliance.txt @@ -3,11 +3,12 @@ # used by ci/check_compliance # zephyr-keep-sorted-start clang-format>=15.0.0 -gitlint +gitlint-core junitparser>=4.0.1 lxml>=5.3.0 pykwalify pylint>=3 +python-dotenv python-magic-bin; sys_platform == "win32" python-magic; sys_platform != "win32" ruff==0.11.11 diff --git a/scripts/requirements-extras.txt b/scripts/requirements-extras.txt index 59f2eb3ff986..2d7a51cf29ab 100644 --- a/scripts/requirements-extras.txt +++ b/scripts/requirements-extras.txt @@ -10,7 +10,7 @@ gitpython>=3.1.41 plotly # helper for developers - check git commit messages -gitlint +gitlint-core # helper for developers junit2html @@ -19,7 +19,7 @@ junit2html lpc_checksum # used by NXP platform to generate/flash firmware images -spsdk == 2.6.0 +spsdk >= 3.0.0 # used by scripts/build/gen_cfb_font_header.py - helper script for user Pillow>=10.3.0 diff --git a/scripts/requirements-run-test.txt b/scripts/requirements-run-test.txt index 6c3f3d93cf8d..4faa17b7b659 100644 --- a/scripts/requirements-run-test.txt +++ b/scripts/requirements-run-test.txt @@ -7,7 +7,6 @@ pyocd>=0.35.0 # used by twister for board/hardware map tabulate -natsort # used by mcuboot cbor>=1.0.0 diff --git a/scripts/west_commands/build.py b/scripts/west_commands/build.py index fb3894944cd8..a271e4075a5b 100644 --- a/scripts/west_commands/build.py +++ b/scripts/west_commands/build.py @@ -642,7 +642,12 @@ def _run_cmake(self, board, origin, cmake_opts): if user_args: cmake_opts.extend(shlex.split(user_args)) - config_sysbuild = config_getboolean('sysbuild', False) + config_sysbuild = config_getboolean('sysbuild', None) + + if config_sysbuild is None: + # If no option is set, then enable sysbuild globally + config_sysbuild = True + if self.args.sysbuild or (config_sysbuild and not self.args.no_sysbuild): cmake_opts.extend([f'-S{SYSBUILD_PROJ_DIR}', f'-DAPP_DIR:PATH={self.source_dir}']) diff --git a/scripts/west_commands/runners/nrf_common.py b/scripts/west_commands/runners/nrf_common.py index afa4665d8f47..75ad66aed99f 100644 --- a/scripts/west_commands/runners/nrf_common.py +++ b/scripts/west_commands/runners/nrf_common.py @@ -53,7 +53,7 @@ class NrfBinaryRunner(ZephyrBinaryRunner): def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False, erase_mode=None, ext_erase_mode=None, reset=True, - tool_opt=None, force=False, recover=False): + tool_opt=None, force=False, recover=False, dry_run=False): super().__init__(cfg) self.hex_ = cfg.hex_file # The old --nrf-family options takes upper-case family names @@ -67,6 +67,7 @@ def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False, self.reset = bool(reset) self.force = force self.recover = bool(recover) + self.dry_run = bool(dry_run) self.tool_opt = [] if tool_opt is not None: @@ -118,7 +119,6 @@ def do_add_parser(cls, parser): choices=['none', 'ranges', 'all'], help='Select the type of erase operation for the ' 'external non-volatile memory') - parser.set_defaults(reset=True) @classmethod @@ -139,7 +139,10 @@ def ensure_snr(self): self.dev_id = [d.lstrip("0") for d in dev_id] return if not dev_id or "*" in dev_id: - dev_id = self.get_board_snr(dev_id or "*") + if not self.dry_run: + dev_id = self.get_board_snr(dev_id or "*") + else: + dev_id = "DEVICEID" # for a dry run self.dev_id = dev_id.lstrip("0") @abc.abstractmethod @@ -357,10 +360,13 @@ def program_hex(self): if not self.erase and regtool_generated_uicr: self.exec_op('erase', core=core, kind='uicr') else: + erase_mode = self._get_erase_mode(self.erase_mode) if self.erase: erase_arg = 'ERASE_ALL' + elif self.erase_mode: + erase_arg = erase_mode elif self.family == 'nrf54l': - erase_arg = self._get_erase_mode(self.erase_mode) or 'ERASE_NONE' + erase_arg = 'ERASE_NONE' else: erase_arg = 'ERASE_RANGES_TOUCHED_BY_FIRMWARE' @@ -479,10 +485,6 @@ def do_run(self, command, **kwargs): self.ensure_family() - if self.family != 'nrf54l' and self.erase_mode: - raise RuntimeError('Option --erase-mode can only be used with the ' - 'nRF54L family.') - self.ensure_output('hex') if IntelHex is None: raise RuntimeError('Python dependency intelhex was missing; ' diff --git a/scripts/west_commands/runners/nrfutil.py b/scripts/west_commands/runners/nrfutil.py index 0490df29ca17..9deb32e06a02 100644 --- a/scripts/west_commands/runners/nrfutil.py +++ b/scripts/west_commands/runners/nrfutil.py @@ -5,6 +5,7 @@ '''Runner for flashing with nrfutil.''' import json +import shlex import subprocess import sys from pathlib import Path @@ -18,12 +19,12 @@ class NrfUtilBinaryRunner(NrfBinaryRunner): def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False, erase_mode=None, ext_erase_mode=None, reset=True, tool_opt=None, - force=False, recover=False, - ext_mem_config_file=None): + force=False, recover=False, ext_mem_config_file=None, + dry_run=False): super().__init__(cfg, family, softreset, pinreset, dev_id, erase, erase_mode, ext_erase_mode, reset, tool_opt, force, - recover) + recover, dry_run) self.ext_mem_config_file = ext_mem_config_file @@ -55,7 +56,8 @@ def do_create(cls, cfg, args): ext_erase_mode=args.ext_erase_mode, reset=args.reset, tool_opt=args.tool_opt, force=args.force, recover=args.recover, - ext_mem_config_file=args.ext_mem_config_file) + ext_mem_config_file=args.ext_mem_config_file, + dry_run=args.dry_run) @classmethod def do_add_parser(cls, parser): @@ -63,15 +65,23 @@ def do_add_parser(cls, parser): parser.add_argument('--ext-mem-config-file', required=False, dest='ext_mem_config_file', help='path to an JSON file with external memory configuration') + parser.add_argument('--dry-run', required=False, + action='store_true', + help='''Generate all the commands without actually + executing them''') - def _exec(self, args): + def _exec(self, args, force=False): jout_all = [] cmd = ['nrfutil', '--json', 'device'] + args - self._log_cmd(cmd) - if _DRY_RUN: - return {} + escaped = ' '.join(shlex.quote(s) for s in cmd) + if _DRY_RUN or (self.dry_run): + self.logger.info(escaped) + if not force: + return {} + else: + self.logger.debug(escaped) with subprocess.Popen(cmd, stdout=subprocess.PIPE) as p: for line in iter(p.stdout.readline, b''): @@ -148,7 +158,7 @@ def _append_batch(self, op, json_file): cmd += ['--core', op['core']] if op.get('core') else [] cmd += ['--x-family', f'{self.family}'] cmd += ['--x-append-batch', f'{json_file}'] - self._exec(cmd) + self._exec(cmd, force=True) def _exec_batch(self): # Use x-append-batch to get the JSON from nrfutil itself diff --git a/scripts/zephyr_module.py b/scripts/zephyr_module.py index c214f51704c8..6606af52ba0f 100755 --- a/scripts/zephyr_module.py +++ b/scripts/zephyr_module.py @@ -386,10 +386,13 @@ def kconfig_snippet(meta, path, kconfig_file=None, blobs=False, taint_blobs=Fals return '\n'.join(snippet) -def process_kconfig_module_dir(module, meta): +def process_kconfig_module_dir(module, meta, cmake_output): module_path = PurePath(module) name_sanitized = meta['name-sanitized'] - return f'ZEPHYR_{name_sanitized.upper()}_MODULE_DIR={module_path.as_posix()}\n' + + if cmake_output is False: + return f'ZEPHYR_{name_sanitized.upper()}_MODULE_DIR={module_path.as_posix()}\n' + return f'list(APPEND kconfig_env_dirs ZEPHYR_{name_sanitized.upper()}_MODULE_DIR={module_path.as_posix()})\n' def process_kconfig(module, meta): @@ -870,6 +873,7 @@ def main(): args = parser.parse_args() kconfig_module_dirs = "" + kconfig_module_dirs_cmake = "set(kconfig_env_dirs)\n" kconfig = "" cmake = "" sysbuild_kconfig = "" @@ -882,7 +886,8 @@ def main(): args.modules, args.extra_modules) for module in modules: - kconfig_module_dirs += process_kconfig_module_dir(module.project, module.meta) + kconfig_module_dirs += process_kconfig_module_dir(module.project, module.meta, False) + kconfig_module_dirs_cmake += process_kconfig_module_dir(module.project, module.meta, True) kconfig += process_kconfig(module.project, module.meta) cmake += process_cmake(module.project, module.meta) sysbuild_kconfig += process_sysbuildkconfig( @@ -894,13 +899,20 @@ def main(): if args.kconfig_out or args.sysbuild_kconfig_out: if args.kconfig_out: kconfig_module_dirs_out = PurePath(args.kconfig_out).parent / 'kconfig_module_dirs.env' + kconfig_module_dirs_cmake_out = PurePath(args.kconfig_out).parent / \ + 'kconfig_module_dirs.cmake' elif args.sysbuild_kconfig_out: kconfig_module_dirs_out = PurePath(args.sysbuild_kconfig_out).parent / \ 'kconfig_module_dirs.env' + kconfig_module_dirs_cmake_out = PurePath(args.sysbuild_kconfig_out).parent / \ + 'kconfig_module_dirs.cmake' with open(kconfig_module_dirs_out, 'w', encoding="utf-8") as fp: fp.write(kconfig_module_dirs) + with open(kconfig_module_dirs_cmake_out, 'w', encoding="utf-8") as fp: + fp.write(kconfig_module_dirs_cmake) + if args.kconfig_out: with open(args.kconfig_out, 'w', encoding="utf-8") as fp: fp.write(kconfig) diff --git a/share/sysbuild/Kconfig b/share/sysbuild/Kconfig index 1a9f36ac7779..b9cec010dd9d 100644 --- a/share/sysbuild/Kconfig +++ b/share/sysbuild/Kconfig @@ -2,8 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -source "$(KCONFIG_ENV_FILE)" - config BOARD string default "$(BOARD)" diff --git a/snippets/bt-ll-sw-split/bt-ll-sw-split.overlay b/snippets/bt-ll-sw-split/bt-ll-sw-split.overlay index 04bf83ef44d4..a57a0e82ba6e 100644 --- a/snippets/bt-ll-sw-split/bt-ll-sw-split.overlay +++ b/snippets/bt-ll-sw-split/bt-ll-sw-split.overlay @@ -2,6 +2,10 @@ status = "okay"; }; +&bt_hci_sdc { + status = "disabled"; +}; + / { chosen { zephyr,bt-hci = &bt_hci_controller; diff --git a/snippets/nordic/nordic-log-stm-dict/boards/nrf54h20_cpuapp.overlay b/snippets/nordic/nordic-log-stm-dict/boards/nrf54h20_cpuapp.overlay index fec548173648..962aa231b7a9 100644 --- a/snippets/nordic/nordic-log-stm-dict/boards/nrf54h20_cpuapp.overlay +++ b/snippets/nordic/nordic-log-stm-dict/boards/nrf54h20_cpuapp.overlay @@ -7,10 +7,7 @@ status = "okay"; }; -&tddconf { +&coresight { status = "okay"; - etrsources = <(NRF_TDDCONF_SOURCE_STMMAINCORE | NRF_TDDCONF_SOURCE_STMPPR | - NRF_TDDCONF_SOURCE_STMFLPR)>; - portconfig = <0>; - etrbuffer = <&etr_buffer>; + mode = "stm-etr"; }; diff --git a/snippets/nordic/nordic-log-stm-dict/boards/nrf54h20_cpurad.overlay b/snippets/nordic/nordic-log-stm-dict/boards/nrf54h20_cpurad.overlay deleted file mode 100644 index 5bdeddd3c07f..000000000000 --- a/snippets/nordic/nordic-log-stm-dict/boards/nrf54h20_cpurad.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor - * SPDX-License-Identifier: Apache-2.0 - */ - -&tddconf { - status = "okay"; - etrsources = <(NRF_TDDCONF_SOURCE_STMMAINCORE)>; -}; diff --git a/snippets/nordic/nordic-log-stm-dict/log_stm_dict.conf b/snippets/nordic/nordic-log-stm-dict/log_stm_dict.conf index 7384e36b92a2..0bd8b46d387e 100644 --- a/snippets/nordic/nordic-log-stm-dict/log_stm_dict.conf +++ b/snippets/nordic/nordic-log-stm-dict/log_stm_dict.conf @@ -3,3 +3,4 @@ CONFIG_TEST_LOGGING_DEFAULTS=n CONFIG_LOG_FRONTEND=y CONFIG_LOG_FRONTEND_ONLY=y CONFIG_LOG_FRONTEND_STMESP=y +CONFIG_DEBUG_DRIVER=y diff --git a/snippets/nordic/nordic-log-stm-dict/snippet.yml b/snippets/nordic/nordic-log-stm-dict/snippet.yml index 6e4f1c6d23e1..a717d39399b5 100644 --- a/snippets/nordic/nordic-log-stm-dict/snippet.yml +++ b/snippets/nordic/nordic-log-stm-dict/snippet.yml @@ -5,6 +5,3 @@ boards: /.*/nrf54h20/cpuapp/: append: EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20_cpuapp.overlay - /.*/nrf54h20/cpurad/: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20_cpurad.overlay diff --git a/snippets/nordic/nordic-log-stm-tpiu-dict/README.rst b/snippets/nordic/nordic-log-stm-tpiu-dict/README.rst new file mode 100644 index 000000000000..9dbf067671bf --- /dev/null +++ b/snippets/nordic/nordic-log-stm-tpiu-dict/README.rst @@ -0,0 +1,11 @@ +.. _nordic-log-stm-tpiu-dict: + +Nordic Dictionary-based STM to TPIU logging snippet (nordic-log-stm-tpiu-dict) +############################################################################## + +Overview +******** + +This snippet allows users to build Zephyr with the dictionary-based logging to +the Coresight STM stimulus ports. Data is written to the TPIU interface and can +be captured with nrfutil trace to translate into a human-readable format. diff --git a/snippets/nordic/nordic-log-stm/boards/nrf54h20_cpurad.overlay b/snippets/nordic/nordic-log-stm-tpiu-dict/boards/nrf54h20_cpuapp.overlay similarity index 54% rename from snippets/nordic/nordic-log-stm/boards/nrf54h20_cpurad.overlay rename to snippets/nordic/nordic-log-stm-tpiu-dict/boards/nrf54h20_cpuapp.overlay index 5bdeddd3c07f..e6f14f46a6a4 100644 --- a/snippets/nordic/nordic-log-stm/boards/nrf54h20_cpurad.overlay +++ b/snippets/nordic/nordic-log-stm-tpiu-dict/boards/nrf54h20_cpuapp.overlay @@ -3,7 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -&tddconf { +&coresight { status = "okay"; - etrsources = <(NRF_TDDCONF_SOURCE_STMMAINCORE)>; + mode = "stm-tpiu"; + pinctrl-0 = <&tpiu_default>; + pinctrl-names = "default"; }; diff --git a/snippets/nordic/nordic-log-stm-tpiu-dict/log_stm_dict.conf b/snippets/nordic/nordic-log-stm-tpiu-dict/log_stm_dict.conf new file mode 100644 index 000000000000..0bd8b46d387e --- /dev/null +++ b/snippets/nordic/nordic-log-stm-tpiu-dict/log_stm_dict.conf @@ -0,0 +1,6 @@ +CONFIG_LOG=y +CONFIG_TEST_LOGGING_DEFAULTS=n +CONFIG_LOG_FRONTEND=y +CONFIG_LOG_FRONTEND_ONLY=y +CONFIG_LOG_FRONTEND_STMESP=y +CONFIG_DEBUG_DRIVER=y diff --git a/snippets/nordic/nordic-log-stm-tpiu-dict/snippet.yml b/snippets/nordic/nordic-log-stm-tpiu-dict/snippet.yml new file mode 100644 index 000000000000..32cd36d377ea --- /dev/null +++ b/snippets/nordic/nordic-log-stm-tpiu-dict/snippet.yml @@ -0,0 +1,7 @@ +name: nordic-log-stm-tpiu-dict +append: + EXTRA_CONF_FILE: log_stm_dict.conf +boards: + /.*/nrf54h20/cpuapp/: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20_cpuapp.overlay diff --git a/snippets/nordic/nordic-log-stm/boards/nrf54h20_cpuapp.overlay b/snippets/nordic/nordic-log-stm/boards/nrf54h20_cpuapp.overlay index fec548173648..962aa231b7a9 100644 --- a/snippets/nordic/nordic-log-stm/boards/nrf54h20_cpuapp.overlay +++ b/snippets/nordic/nordic-log-stm/boards/nrf54h20_cpuapp.overlay @@ -7,10 +7,7 @@ status = "okay"; }; -&tddconf { +&coresight { status = "okay"; - etrsources = <(NRF_TDDCONF_SOURCE_STMMAINCORE | NRF_TDDCONF_SOURCE_STMPPR | - NRF_TDDCONF_SOURCE_STMFLPR)>; - portconfig = <0>; - etrbuffer = <&etr_buffer>; + mode = "stm-etr"; }; diff --git a/snippets/nordic/nordic-log-stm/log_stm.conf b/snippets/nordic/nordic-log-stm/log_stm.conf index 1325c25b505f..46550a258cd1 100644 --- a/snippets/nordic/nordic-log-stm/log_stm.conf +++ b/snippets/nordic/nordic-log-stm/log_stm.conf @@ -4,3 +4,4 @@ CONFIG_LOG_FRONTEND=y CONFIG_LOG_FRONTEND_ONLY=y CONFIG_LOG_FRONTEND_STMESP=y CONFIG_LOG_FRONTEND_STMESP_FSC=y +CONFIG_DEBUG_DRIVER=y diff --git a/snippets/nordic/nordic-log-stm/snippet.yml b/snippets/nordic/nordic-log-stm/snippet.yml index 0a984a8312cc..918379360afc 100644 --- a/snippets/nordic/nordic-log-stm/snippet.yml +++ b/snippets/nordic/nordic-log-stm/snippet.yml @@ -5,6 +5,3 @@ boards: /.*/nrf54h20/cpuapp/: append: EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20_cpuapp.overlay - /.*/nrf54h20/cpurad/: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20_cpurad.overlay diff --git a/soc/nordic/Kconfig b/soc/nordic/Kconfig index d86e98e3dbc7..46efc8c2c744 100644 --- a/soc/nordic/Kconfig +++ b/soc/nordic/Kconfig @@ -197,6 +197,15 @@ config NRF_SECURE_APPROTECT_USER_HANDLING endchoice +config NRF_SKIP_CLOCK_CONFIG + bool + prompt "Skip clock frequency configuration" if TRUSTED_EXECUTION_SECURE + depends on NRF_PLATFORM_LUMOS + default y if TRUSTED_EXECUTION_NONSECURE + help + With this option, the CPU clock frequency is not set during system initialization. + The CPU runs with the default, hardware-selected frequency. + config NRF_TRACE_PORT bool "nRF TPIU" depends on !SOC_SERIES_NRF51X @@ -212,4 +221,11 @@ config NRF_PLATFORM_HALTIUM this option. This allows to easily enable common functionality on SoCs based on the Haltium platform. +config NRF_PLATFORM_LUMOS + bool + help + SoC series based on the Nordic nRF Lumos platform such as nRF54Lx + series. This allows to easily enable common functionality on + SoCs based on the Lumos platform. + endif # SOC_FAMILY_NORDIC_NRF diff --git a/soc/nordic/common/Kconfig b/soc/nordic/common/Kconfig index 782d9452b677..e1fcd713c77c 100644 --- a/soc/nordic/common/Kconfig +++ b/soc/nordic/common/Kconfig @@ -48,5 +48,22 @@ source "subsys/logging/Kconfig.template.log_config" endif # MRAM_LATENCY +if HAS_NORDIC_DMM + +config DMM_HEAP_CHUNKS + int "Number of chunks in the DMM heap" + default 32 + help + DMM is using a simplified heap which is using 32 bit mask to allocate + required buffer which consists of contiguous chunks. If there are many + small buffers used with DMM it is possible that allocation will fail. + Number of chunks is a trade-off between performance and granularity. + Must be multiply of 32. + +config DMM_STATS + bool "Usage statistics" + +endif # HAS_NORDIC_DMM + rsource "vpr/Kconfig" rsource "uicr/Kconfig" diff --git a/soc/nordic/common/Kconfig.defconfig b/soc/nordic/common/Kconfig.defconfig index 077a73ad24d9..846151dd11a8 100644 --- a/soc/nordic/common/Kconfig.defconfig +++ b/soc/nordic/common/Kconfig.defconfig @@ -6,3 +6,6 @@ if RISCV_CORE_NORDIC_VPR rsource "vpr/Kconfig.defconfig" endif # RISCV_CORE_NORDIC_VPR + +config PM_DEVICE_RUNTIME_DEFAULT_ENABLE + default y if PM_DEVICE_RUNTIME diff --git a/soc/nordic/common/Kconfig.peripherals b/soc/nordic/common/Kconfig.peripherals index d7e489b446a5..fa7fd2a411aa 100644 --- a/soc/nordic/common/Kconfig.peripherals +++ b/soc/nordic/common/Kconfig.peripherals @@ -13,10 +13,12 @@ config HAS_HW_NRF_BPROT def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_BPROT)) config HAS_HW_NRF_CC310 - def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_310)) + def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_310)) || \ + ($(dt_nodelabel_enabled,psa_rng) && SOC_SERIES_NRF91X) config HAS_HW_NRF_CC312 - def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_312)) + def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_312)) || \ + ($(dt_nodelabel_enabled,psa_rng) && SOC_NRF5340_CPUAPP) config HAS_HW_NRF_CCM def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_CCM)) diff --git a/soc/nordic/common/dmm.c b/soc/nordic/common/dmm.c index 0b4e42f8c6de..ac22f8ee430a 100644 --- a/soc/nordic/common/dmm.c +++ b/soc/nordic/common/dmm.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include "dmm.h" @@ -26,6 +26,9 @@ .dt_align = DMM_REG_ALIGN_SIZE(node_id), \ .dt_allc = &_BUILD_LINKER_END_VAR(node_id)}, +#define HEAP_NUM_WORDS (CONFIG_DMM_HEAP_CHUNKS / 32) +BUILD_ASSERT(IS_ALIGNED(CONFIG_DMM_HEAP_CHUNKS, 32)); + /* Generate declarations of linker variables used to determine size of preallocated variables * stored in memory sections spanning over memory regions. * These are used to determine memory left for dynamic bounce buffer allocator to work with. @@ -42,9 +45,18 @@ struct dmm_region { }; struct dmm_heap { - struct sys_heap heap; + uint32_t mask[HEAP_NUM_WORDS]; + atomic_t tail_mask[HEAP_NUM_WORDS]; + uintptr_t ptr; + uintptr_t ptr_end; + size_t blk_size; const struct dmm_region *region; + sys_bitarray_t bitarray; +#ifdef CONFIG_DMM_STATS + atomic_t curr_use; + uint32_t max_use; struct k_spinlock lock; +#endif }; static const struct dmm_region dmm_regions[] = { @@ -55,7 +67,6 @@ struct { struct dmm_heap dmm_heaps[ARRAY_SIZE(dmm_regions)]; } dmm_heaps_data; - static struct dmm_heap *dmm_heap_find(void *region) { struct dmm_heap *dh; @@ -103,37 +114,154 @@ static bool is_user_buffer_correctly_preallocated(void const *user_buffer, size_ return false; } -static size_t dmm_heap_start_get(struct dmm_heap *dh) +/* Function updates the tail bits mask after the allocation. Tail bits are all bits + * except the head. Tail bits mask together with a known index of the start of + * chunk (because freeing has a buffer address) allows to determine the size of the + * buffer (how many chunks were included. Because tail_mask is updated after allocation + * we can safely modify bits that represents allocated buffer, we only need to use + * atomic operation on the mask since mask may be modified (but different bits). + */ +static void tail_mask_set(atomic_t *tail_mask, size_t num_bits, size_t off) { - return ROUND_UP(dh->region->dt_allc, dh->region->dt_align); + size_t tail_bits = num_bits - 1; + size_t tail_off = off + 1; + + if (tail_bits == 0) { + return; + } + + if (HEAP_NUM_WORDS == 1) { + atomic_or(tail_mask, BIT_MASK(tail_bits) << tail_off); + return; + } + + size_t idx = tail_off / 32; + atomic_t *t_mask = &tail_mask[idx]; + + tail_off = tail_off % 32; + while (tail_bits > 0) { + uint32_t bits = MIN(32 - tail_off, tail_bits); + uint32_t mask = (bits == 32) ? UINT32_MAX : (BIT_MASK(bits) << tail_off); + + atomic_or(t_mask, mask); + t_mask++; + tail_off = 0; + tail_bits -= bits; + } } -static size_t dmm_heap_size_get(struct dmm_heap *dh) +/* Function determines how many chunks were used for the allocated buffer. It is + * determined from tail bits mask and index of the starting chunk (%p off). + * Function is called before bits are freed in the bitarray so we can safely modify + * bits that belong to that buffer. + * + * @param tail_mask Pointer to tail_mask array. + * @param off Index of the start of the buffer. + * + * @return Number of chunks that forms the buffer that will be freed. + */ +static uint32_t num_bits_get(atomic_t *tail_mask, size_t off) { - return (dh->region->dt_size - (dmm_heap_start_get(dh) - dh->region->dt_addr)); + uint32_t num_bits = 1; + size_t tail_off = off + 1; + size_t idx = tail_off / 32; + atomic_t *t_mask = &tail_mask[idx]; + + tail_off = tail_off % 32; + do { + uint32_t mask = (uint32_t)*t_mask >> tail_off; + + if (mask == UINT32_MAX) { + num_bits += 32; + atomic_set(t_mask, 0); + } else { + uint32_t bits = __builtin_ctz(~mask); + + if (bits == 0) { + break; + } + + num_bits += bits; + atomic_and(t_mask, ~(BIT_MASK(bits) << tail_off)); + + if (bits + tail_off < 32) { + break; + } + + tail_off = 0; + } + + t_mask++; + } while ((HEAP_NUM_WORDS > 1) && (t_mask != &tail_mask[HEAP_NUM_WORDS])); + + return num_bits; } static void *dmm_buffer_alloc(struct dmm_heap *dh, size_t length) { - void *ret; - k_spinlock_key_t key; + size_t num_bits, off; + int rv; + + if (dh->ptr == 0) { + /* Not initialized. */ + return NULL; + } length = ROUND_UP(length, dh->region->dt_align); + num_bits = DIV_ROUND_UP(length, dh->blk_size); + + rv = sys_bitarray_alloc(&dh->bitarray, num_bits, &off); + if (rv < 0) { + return NULL; + } + + tail_mask_set(dh->tail_mask, num_bits, off); + +#ifdef CONFIG_DMM_STATS + k_spinlock_key_t key; key = k_spin_lock(&dh->lock); - ret = sys_heap_aligned_alloc(&dh->heap, dh->region->dt_align, length); + dh->curr_use += num_bits; + dh->max_use = MAX(dh->max_use, dh->curr_use); k_spin_unlock(&dh->lock, key); +#endif - return ret; + return (void *)(dh->ptr + dh->blk_size * off); } static void dmm_buffer_free(struct dmm_heap *dh, void *buffer) { - k_spinlock_key_t key; + size_t offset = ((uintptr_t)buffer - dh->ptr) / dh->blk_size; + size_t num_bits = num_bits_get(dh->tail_mask, offset); + int rv; + +#ifdef CONFIG_DMM_STATS + atomic_sub(&dh->curr_use, num_bits); +#endif + rv = sys_bitarray_free(&dh->bitarray, num_bits, offset); + (void)rv; + __ASSERT_NO_MSG(rv == 0); +} - key = k_spin_lock(&dh->lock); - sys_heap_free(&dh->heap, buffer); - k_spin_unlock(&dh->lock, key); +static void dmm_memcpy(void *dst, const void *src, size_t len) +{ +#define IS_ALIGNED32(x) IS_ALIGNED(x, sizeof(uint32_t)) +#define IS_ALIGNED64(x) IS_ALIGNED(x, sizeof(uint64_t)) + if (IS_ALIGNED64(len) && IS_ALIGNED64(dst) && IS_ALIGNED64(src)) { + for (uint32_t i = 0; i < len / sizeof(uint64_t); i++) { + ((uint64_t *)dst)[i] = ((uint64_t *)src)[i]; + } + return; + } + + if (IS_ALIGNED32(len) && IS_ALIGNED32(dst) && IS_ALIGNED32(src)) { + for (uint32_t i = 0; i < len / sizeof(uint32_t); i++) { + ((uint32_t *)dst)[i] = ((uint32_t *)src)[i]; + } + return; + } + + memcpy(dst, src, len); } int dmm_buffer_out_prepare(void *region, void const *user_buffer, size_t user_length, @@ -172,7 +300,7 @@ int dmm_buffer_out_prepare(void *region, void const *user_buffer, size_t user_le return -ENOMEM; } /* - copy user buffer contents into allocated buffer */ - memcpy(*buffer_out, user_buffer, user_length); + dmm_memcpy(*buffer_out, user_buffer, user_length); } /* Check if device memory region is cacheable @@ -201,7 +329,7 @@ int dmm_buffer_out_release(void *region, void *buffer_out) /* Check if output buffer is contained within memory area * managed by dynamic memory allocator */ - if (is_buffer_within_region(addr, 0, dmm_heap_start_get(dh), dmm_heap_size_get(dh))) { + if (is_buffer_within_region(addr, 0, dh->ptr, dh->ptr_end)) { /* If yes, free the buffer */ dmm_buffer_free(dh, buffer_out); } @@ -281,14 +409,14 @@ int dmm_buffer_in_release(void *region, void *user_buffer, size_t user_length, v * If no, copy allocated buffer to the user buffer */ if (buffer_in != user_buffer) { - memcpy(user_buffer, buffer_in, user_length); + dmm_memcpy(user_buffer, buffer_in, user_length); } /* If yes, no action is needed */ /* Check if input buffer is contained within memory area * managed by dynamic memory allocator */ - if (is_buffer_within_region(addr, 0, dmm_heap_start_get(dh), dmm_heap_size_get(dh))) { + if (is_buffer_within_region(addr, user_length, dh->ptr, dh->ptr_end)) { /* If yes, free the buffer */ dmm_buffer_free(dh, buffer_in); } @@ -297,14 +425,51 @@ int dmm_buffer_in_release(void *region, void *user_buffer, size_t user_length, v return 0; } +int dmm_stats_get(void *region, uintptr_t *start_addr, uint32_t *curr_use, uint32_t *max_use) +{ +#ifdef CONFIG_DMM_STATS + struct dmm_heap *dh; + + dh = dmm_heap_find(region); + if (dh == NULL) { + return -EINVAL; + } + + if (start_addr) { + *start_addr = dh->ptr; + } + + if (curr_use) { + *curr_use = (100 * dh->curr_use) / dh->bitarray.num_bits; + } + + if (max_use) { + *max_use = (100 * dh->max_use) / dh->bitarray.num_bits; + } + + return 0; +#else + return -ENOTSUP; +#endif +} + int dmm_init(void) { struct dmm_heap *dh; + int blk_cnt; + int heap_space; for (size_t idx = 0; idx < ARRAY_SIZE(dmm_regions); idx++) { dh = &dmm_heaps_data.dmm_heaps[idx]; dh->region = &dmm_regions[idx]; - sys_heap_init(&dh->heap, (void *)dmm_heap_start_get(dh), dmm_heap_size_get(dh)); + dh->ptr = ROUND_UP(dh->region->dt_allc, dh->region->dt_align); + heap_space = dh->region->dt_size - (dh->ptr - dh->region->dt_addr); + dh->blk_size = ROUND_UP(heap_space / (32 * HEAP_NUM_WORDS), dh->region->dt_align); + blk_cnt = heap_space / dh->blk_size; + dh->ptr_end = dh->ptr + blk_cnt * dh->blk_size; + dh->bitarray.num_bits = blk_cnt; + dh->bitarray.num_bundles = HEAP_NUM_WORDS; + dh->bitarray.bundles = dh->mask; } return 0; diff --git a/soc/nordic/common/dmm.h b/soc/nordic/common/dmm.h index 34b517c92dfc..09486289aa60 100644 --- a/soc/nordic/common/dmm.h +++ b/soc/nordic/common/dmm.h @@ -35,12 +35,12 @@ extern "C" { * Cache line alignment is required if region is cacheable and data cache is enabled. */ #define DMM_REG_ALIGN_SIZE(node_id) \ - (DMM_IS_REG_CACHEABLE(node_id) ? CONFIG_DCACHE_LINE_SIZE : sizeof(uint8_t)) + (DMM_IS_REG_CACHEABLE(node_id) ? CONFIG_DCACHE_LINE_SIZE : sizeof(uint32_t)) #else #define DMM_IS_REG_CACHEABLE(node_id) 0 -#define DMM_REG_ALIGN_SIZE(node_id) (sizeof(uint8_t)) +#define DMM_REG_ALIGN_SIZE(node_id) (sizeof(uint32_t)) #endif /* CONFIG_DCACHE */ @@ -163,6 +163,22 @@ int dmm_buffer_in_prepare(void *region, void *user_buffer, size_t user_length, v */ int dmm_buffer_in_release(void *region, void *user_buffer, size_t user_length, void *buffer_in); +/** + * @brief Get statistics. + * + * Must be enabled with CONFIG_DMM_STATS. + * + * @param[in] region DMM memory region. + * @param[out] start_addr Location where starting address of the memory region is set. Can be null. + * @param[out] curr_use Location where current use in percent is written. Can be null. + * @param[out] max_use Location where maximum use in percent is written. Can be null. + * + * @retval 0 on success. + * @retval -EINVAL Invalid region. + * @retval -ENOTSUP Feature is disabled. + */ +int dmm_stats_get(void *region, uintptr_t *start_addr, uint32_t *curr_use, uint32_t *max_use); + /** * @brief Initialize DMM. * @@ -210,6 +226,17 @@ static ALWAYS_INLINE int dmm_buffer_in_release(void *region, void *user_buffer, return 0; } +static ALWAYS_INLINE int dmm_stats_get(void *region, uintptr_t *start_addr, + uint32_t *curr_use, uint32_t *max_use) +{ + ARG_UNUSED(region); + ARG_UNUSED(start_addr); + ARG_UNUSED(curr_use); + ARG_UNUSED(max_use); + + return 0; +} + static ALWAYS_INLINE int dmm_init(void) { return 0; diff --git a/soc/nordic/common/nrf54hx_nrf92x_mpu_regions.c b/soc/nordic/common/nrf54hx_nrf92x_mpu_regions.c index a9e8b3de7a91..14b63a6481c9 100644 --- a/soc/nordic/common/nrf54hx_nrf92x_mpu_regions.c +++ b/soc/nordic/common/nrf54hx_nrf92x_mpu_regions.c @@ -22,10 +22,12 @@ #define SOFTPERIPH_SIZE DT_REG_SIZE(DT_NODELABEL(softperiph_ram)) static struct arm_mpu_region mpu_regions[] = { +#ifdef CONFIG_XIP MPU_REGION_ENTRY("FLASH_0", CONFIG_FLASH_BASE_ADDRESS, REGION_FLASH_ATTR(CONFIG_FLASH_BASE_ADDRESS, CONFIG_FLASH_SIZE * 1024)), +#endif MPU_REGION_ENTRY("SRAM_0", CONFIG_SRAM_BASE_ADDRESS, REGION_RAM_ATTR(CONFIG_SRAM_BASE_ADDRESS, diff --git a/soc/nordic/common/uicr/CMakeLists.txt b/soc/nordic/common/uicr/CMakeLists.txt index 1ec3a35c5665..d350d8d3f586 100644 --- a/soc/nordic/common/uicr/CMakeLists.txt +++ b/soc/nordic/common/uicr/CMakeLists.txt @@ -4,3 +4,27 @@ if(CONFIG_NRF_PERIPHCONF_SECTION) zephyr_linker_sources(SECTIONS uicr.ld) endif() + +if(CONFIG_NRF_PERIPHCONF_GENERATE_ENTRIES) + set(periphconf_entries_c_file ${PROJECT_BINARY_DIR}/periphconf_entries_generated.c) + execute_process( + COMMAND + ${CMAKE_COMMAND} -E env ZEPHYR_BASE=${ZEPHYR_BASE} + ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/gen_periphconf_entries.py + --soc ${CONFIG_SOC} + --in-edt-pickle ${EDT_PICKLE} + --out-periphconf-source ${periphconf_entries_c_file} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + COMMAND_ERROR_IS_FATAL ANY + ) + zephyr_sources(${periphconf_entries_c_file}) + message(STATUS "Generated ${periphconf_entries_c_file} from ${EDT_PICKLE}") +endif() + +if(CONFIG_NRF_PERIPHCONF_SECTION AND NOT SYSBUILD) + message(WARNING "CONFIG_NRF_PERIPHCONF_SECTION is enabled, but Sysbuild is not being used. " + "The global peripheral configuration will not be applied unless artifacts " + "are generated manually/externally. To enable automatic generation, build with " + "Sysbuild and ensure that SB_CONFIG_NRF_HALTIUM_GENERATE_UICR=y." + ) +endif() diff --git a/soc/nordic/common/uicr/Kconfig b/soc/nordic/common/uicr/Kconfig index 3c4c6c8219b6..c3a69c3dbe0f 100644 --- a/soc/nordic/common/uicr/Kconfig +++ b/soc/nordic/common/uicr/Kconfig @@ -3,9 +3,36 @@ config NRF_PERIPHCONF_SECTION bool "Populate global peripheral initialization section" - default y if SOC_NRF54H20_CPUAPP || SOC_NRF54H20_CPURAD + default y if SOC_NRF54H20_CPUAPP || SOC_NRF54H20_CPURAD || SOC_NRF9280_CPUAPP depends on LINKER_DEVNULL_SUPPORT imply LINKER_DEVNULL_MEMORY help Include static global domain peripheral initialization values from the build in a dedicated section in the devnull region. + +config NRF_PERIPHCONF_GENERATE_ENTRIES + bool "Generate PERIPHCONF entries source file" + default y if SOC_NRF54H20_CPUAPP || SOC_NRF54H20_CPURAD || SOC_NRF9280_CPUAPP + depends on NRF_PERIPHCONF_SECTION + depends on NRF_PLATFORM_HALTIUM + help + Generate a C file containing PERIPHCONF entries based on the + device configuration in the devicetree. + +config IS_IRONSIDE_SE_SECONDARY_IMAGE + bool "Ironside SE secondary image indicator (informative only, do not change)" + help + This Kconfig is set by sysbuild to indicate that this image is a + secondary firmware for Ironside SE. This is used by the UICR generation + system to determine which PERIPHCONF partition to use. + +config IS_GEN_UICR_IMAGE + bool "UICR generator image indicator (informative only, do not change)" + help + This Kconfig is automatically set when building the gen_uicr image. + It indicates that this is the UICR generator utility image and enables + the UICR generator configuration options. + +# Source UICR generator options when building the gen_uicr image +# All options are disabled by default unless IS_GEN_UICR_IMAGE is set +rsource "Kconfig.gen_uicr" diff --git a/soc/nordic/common/uicr/Kconfig.gen_uicr b/soc/nordic/common/uicr/Kconfig.gen_uicr new file mode 100644 index 000000000000..4ee6af87eaef --- /dev/null +++ b/soc/nordic/common/uicr/Kconfig.gen_uicr @@ -0,0 +1,277 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +menu "UICR generator options" + depends on IS_GEN_UICR_IMAGE + +config GEN_UICR_GENERATE_PERIPHCONF + bool "Generate PERIPHCONF hex alongside UICR" + default y + help + When enabled, the UICR generator will populate the + periphconf_partition partition. + +config GEN_UICR_SECURESTORAGE + bool "UICR.SECURESTORAGE" + default y + depends on $(dt_nodelabel_enabled,secure_storage_partition) + help + When enabled, the UICR generator will configure the + secure storage region based on device tree partitions. + + The following device tree partitions are used: + - secure_storage_partition: Main secure storage partition (required) + - cpuapp_crypto_partition: Application processor crypto storage (optional) + - cpurad_crypto_partition: Radio core crypto storage (optional) + - cpuapp_its_partition: Application processor internal trusted storage (optional) + - cpurad_its_partition: Radio core internal trusted storage (optional) + + Requirements: + - The secure_storage_partition address and size must be aligned to 4KB + - All subpartitions must be multiples of 1KB and laid out contiguously + without gaps + - At least one subpartition must be defined + - Combined subpartition sizes must equal secure_storage_partition size + +config GEN_UICR_LOCK + bool "UICR.LOCK" + help + When enabled, locks the entire contents of the NVR0 page located in + MRAM10. This includes all values in both the UICR and the BICR (Board + Information Configuration Registers). Once locked, the UICR can only + be modified by performing an ERASEALL operation. + + This should be enabled only in production devices to prevent + unauthorized modification. + +config GEN_UICR_ERASEPROTECT + bool "UICR.ERASEPROTECT" + depends on ! GEN_UICR_LOCK + help + When enabled, ERASEALL operations are blocked. + + This option is mutually exclusive with UICR.LOCK in Kconfig to prevent + accidental configuration where both are enabled simultaneously. If both + were enabled, the UICR would become impossible to modify in any way. + Note that gen_uicr.py can be used directly to create a configuration + with both enabled if needed. + +menu "UICR.APPROTECT - Access Port Protection" + +config GEN_UICR_APPROTECT_APPLICATION_PROTECTED + bool "Protect application domain access port" + help + When enabled, disables debug access to the application domain processor, + preventing debugger connection to application memory, registers, and debug + features. When disabled, full debug access is enabled. + +config GEN_UICR_APPROTECT_RADIOCORE_PROTECTED + bool "Protect radio core access port" + help + When enabled, disables debug access to the radio core processor, + preventing debugger connection to radio core memory, registers, and debug + features. When disabled, full debug access is enabled. + +config GEN_UICR_APPROTECT_CORESIGHT_PROTECTED + bool "Disable CoreSight subsystem" + help + When enabled will disable the coresight subsystem, preventing + system level trace features. + +endmenu + +config GEN_UICR_PROTECTEDMEM + bool "UICR.PROTECTEDMEM" + help + When enabled, the UICR generator will configure the + protected memory region. + +config GEN_UICR_PROTECTEDMEM_SIZE_BYTES + int "Protected memory size in bytes" + default 4096 + depends on GEN_UICR_PROTECTEDMEM + help + Size of the protected memory region in bytes. + This value must be divisible by 4096 (4 kiB). + +config GEN_UICR_WDTSTART + bool "UICR.WDTSTART" + help + When enabled, the UICR generator will configure an application + domain watchdog timer to start automatically before the + application core is booted. + +choice GEN_UICR_WDTSTART_INSTANCE + prompt "Watchdog timer instance" + depends on GEN_UICR_WDTSTART + default GEN_UICR_WDTSTART_INSTANCE_WDT0 + help + Select which watchdog timer instance to use. + +config GEN_UICR_WDTSTART_INSTANCE_WDT0 + bool "WDT0" + help + Use watchdog timer instance 0. + +config GEN_UICR_WDTSTART_INSTANCE_WDT1 + bool "WDT1" + help + Use watchdog timer instance 1. + +endchoice + +config GEN_UICR_WDTSTART_INSTANCE_CODE + hex + default 0xBD2328A8 if GEN_UICR_WDTSTART_INSTANCE_WDT0 + default 0x1730C77F if GEN_UICR_WDTSTART_INSTANCE_WDT1 + depends on GEN_UICR_WDTSTART + +config GEN_UICR_WDTSTART_CRV + int "Initial Counter Reload Value (CRV)" + default 65535 + range 15 4294967295 + depends on GEN_UICR_WDTSTART + help + Initial Counter Reload Value (CRV) for the watchdog timer. + This value determines the watchdog timeout period. + Must be at least 15 (0xF) to ensure proper watchdog operation. + Default value 65535 creates a 2-second timeout. + +config GEN_UICR_SECONDARY_WDTSTART + bool "UICR.SECONDARY.WDTSTART" + depends on GEN_UICR_SECONDARY + help + When enabled, the UICR generator will configure the + watchdog timer to start automatically before the + secondary firmware is booted. + +choice GEN_UICR_SECONDARY_WDTSTART_INSTANCE + prompt "Secondary watchdog timer instance" + depends on GEN_UICR_SECONDARY_WDTSTART + default GEN_UICR_SECONDARY_WDTSTART_INSTANCE_WDT0 + help + Select which watchdog timer instance to use for secondary firmware. + +config GEN_UICR_SECONDARY_WDTSTART_INSTANCE_WDT0 + bool "WDT0" + help + Use watchdog timer instance 0 for secondary firmware. + +config GEN_UICR_SECONDARY_WDTSTART_INSTANCE_WDT1 + bool "WDT1" + help + Use watchdog timer instance 1 for secondary firmware. + +endchoice + +config GEN_UICR_SECONDARY_WDTSTART_INSTANCE_CODE + hex + default 0xBD2328A8 if GEN_UICR_SECONDARY_WDTSTART_INSTANCE_WDT0 + default 0x1730C77F if GEN_UICR_SECONDARY_WDTSTART_INSTANCE_WDT1 + depends on GEN_UICR_SECONDARY_WDTSTART + +config GEN_UICR_SECONDARY_WDTSTART_CRV + int "Secondary initial Counter Reload Value (CRV)" + default 65535 + range 15 4294967295 + depends on GEN_UICR_SECONDARY_WDTSTART + help + Initial Counter Reload Value (CRV) for the secondary watchdog timer. + This value determines the watchdog timeout period. + Must be at least 15 (0xF) to ensure proper watchdog operation. + Default value 65535 creates a 2-second timeout. + +config GEN_UICR_SECONDARY + bool "UICR.SECONDARY.ENABLE" + +if GEN_UICR_SECONDARY + +config GEN_UICR_SECONDARY_GENERATE_PERIPHCONF + bool "Generate SECONDARY.PERIPHCONF hex alongside UICR" + default y + help + When enabled, the UICR generator will populate the + secondary_periphconf_partition partition. + +choice GEN_UICR_SECONDARY_PROCESSOR + prompt "Secondary processor selection" + default GEN_UICR_SECONDARY_PROCESSOR_APPLICATION + help + Processor to boot for the secondary firmware. + +config GEN_UICR_SECONDARY_PROCESSOR_APPLICATION + bool "APPLICATION processor" + help + Boot secondary firmware on the APPLICATION processor. + +config GEN_UICR_SECONDARY_PROCESSOR_RADIOCORE + bool "RADIOCORE processor" + help + Boot secondary firmware on the RADIOCORE processor. + +endchoice + +config GEN_UICR_SECONDARY_PROCESSOR_VALUE + hex + default 0xBD2328A8 if GEN_UICR_SECONDARY_PROCESSOR_APPLICATION + default 0x1730C77F if GEN_UICR_SECONDARY_PROCESSOR_RADIOCORE + +config GEN_UICR_SECONDARY_TRIGGER + bool "UICR.SECONDARY.TRIGGER" + help + When enabled, configures automatic triggers that cause IronSide SE + to boot the secondary firmware instead of the primary firmware based + on specific reset reasons. + +if GEN_UICR_SECONDARY_TRIGGER + +config GEN_UICR_SECONDARY_TRIGGER_APPLICATIONWDT0 + bool "Trigger on Application domain watchdog 0 reset" + help + Boot secondary firmware when Application domain watchdog 0 causes a reset. + +config GEN_UICR_SECONDARY_TRIGGER_APPLICATIONWDT1 + bool "Trigger on Application domain watchdog 1 reset" + help + Boot secondary firmware when Application domain watchdog 1 causes a reset. + +config GEN_UICR_SECONDARY_TRIGGER_APPLICATIONLOCKUP + bool "Trigger on Application domain CPU lockup reset" + help + Boot secondary firmware when Application domain CPU lockup causes a reset. + +config GEN_UICR_SECONDARY_TRIGGER_RADIOCOREWDT0 + bool "Trigger on Radio core watchdog 0 reset" + help + Boot secondary firmware when Radio core watchdog 0 causes a reset. + +config GEN_UICR_SECONDARY_TRIGGER_RADIOCOREWDT1 + bool "Trigger on Radio core watchdog 1 reset" + help + Boot secondary firmware when Radio core watchdog 1 causes a reset. + +config GEN_UICR_SECONDARY_TRIGGER_RADIOCORELOCKUP + bool "Trigger on Radio core CPU lockup reset" + help + Boot secondary firmware when Radio core CPU lockup causes a reset. + +endif # GEN_UICR_SECONDARY_TRIGGER + +config GEN_UICR_SECONDARY_PROTECTEDMEM + bool "UICR.SECONDARY.PROTECTEDMEM" + depends on GEN_UICR_SECONDARY + help + When enabled, the UICR generator will configure the + protected memory region for the secondary firmware. + +config GEN_UICR_SECONDARY_PROTECTEDMEM_SIZE_BYTES + int "Secondary protected memory size in bytes" + default 4096 + depends on GEN_UICR_SECONDARY_PROTECTEDMEM + help + Size of the secondary protected memory region in bytes. + This value must be divisible by 4096 (4 kiB). + +endif # GEN_UICR_SECONDARY + +endmenu diff --git a/soc/nordic/common/uicr/Kconfig.sysbuild b/soc/nordic/common/uicr/Kconfig.sysbuild index eb885beaaaf7..6a9341f90994 100644 --- a/soc/nordic/common/uicr/Kconfig.sysbuild +++ b/soc/nordic/common/uicr/Kconfig.sysbuild @@ -3,7 +3,7 @@ config NRF_HALTIUM_GENERATE_UICR bool "Generate UICR file" - depends on SOC_SERIES_NRF54HX + depends on SOC_SERIES_NRF54HX || SOC_SERIES_NRF92X default y help Generate UICR HEX file. diff --git a/soc/nordic/common/uicr/gen_periphconf_entries.py b/soc/nordic/common/uicr/gen_periphconf_entries.py new file mode 100644 index 000000000000..13df5e468ded --- /dev/null +++ b/soc/nordic/common/uicr/gen_periphconf_entries.py @@ -0,0 +1,715 @@ +""" +Copyright (c) 2025 Nordic Semiconductor ASA +SPDX-License-Identifier: Apache-2.0 +""" + +from __future__ import annotations + +import argparse +import enum +import os +import pickle +import sys +from pathlib import Path +from typing import Any + +try: + ZEPHYR_BASE = Path(os.environ["ZEPHYR_BASE"]).resolve() +except KeyError: + sys.exit("Set the environment variable 'ZEPHYR_BASE' to point to the zephyr root directory") + +# Add packages that are located in zephyr itself to the python path so we can import them below +sys.path.insert(0, str(ZEPHYR_BASE / "scripts/dts/python-devicetree/src")) +sys.path.insert(0, str(ZEPHYR_BASE / "soc/nordic/common/uicr")) + +from periphconf.builder import ( + Ctrlsel, + FixedPPIMap, + Node, + NrfCompChannel, + NrfFun, + NrfPsel, + NrfSaadcChannel, + PeriphconfBuilder, + ProcessorId, + SocLookupTables, + dt_processor_id, +) + +# These peripherals are special cases that don't fit the general rules we use to generate +# PERIPHCONF entries based on the devicetree. +NODELABEL_TO_KWARGS = { + # Channel links on this node do not result in PPIB connections, because the *-links properties + # are ambiguous. Instead, the PPIB connections are configured by the DPPICs connected to this. + "dppic130": {"add_ppib_channel_links": False}, + # The interrupts for this node are not managed in IRQMAP. + "canpll": {"has_irq_mapping": False}, +} + + +def get_additional_node_kwargs(node: Node) -> dict[str, Any]: + additional_kwargs = {} + for label in node.labels: + additional_kwargs.update(NODELABEL_TO_KWARGS.get(label, {})) + return additional_kwargs + + +class Family(enum.Enum): + """Families of SoCs supported by this script""" + + SERIES_NRF54HX = "nrf54h" + SERIES_NRF92X = "nrf92" + SERIES_UNKNOWN = "unknown" + + @classmethod + def family(cls, soc): + if soc.startswith("nrf54h") and len(soc) == 8: + return cls.SERIES_NRF54HX + elif soc.startswith("nrf92") and len(soc) == 7: + return cls.SERIES_NRF92X + else: + return cls.SERIES_UNKNOWN + + +class Soc(enum.Enum): + """Names of SoCs supported by this script""" + + NRF54H20 = "nrf54h20" + NRF9280 = "nrf9280" + UNKNOWN = "unknown" + + @classmethod + def soc(cls, soc): + if soc.startswith("nrf54h20") and len(soc) == 8: + return cls.NRF54H20 + elif soc.startswith("nrf9280") and len(soc) == 7: + return cls.NRF9280 + else: + return cls.UNKNOWN + + +def validate_soc_choice(soc): + """Helper for argparse to validate soc parameter type""" + + if (soc.startswith("nrf54h") and soc[6:].isdigit() and len(soc) == 8) or ( + soc.startswith("nrf92") and soc[5:].isdigit() and len(soc) == 7 + ): + return soc + else: + raise argparse.ArgumentTypeError( + f"Invalid soc '{soc}'. Must start with 'nrf54h' or 'nrf92' followed by 2 digits." + ) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + allow_abbrev=False, + description=( + "Generate a C source file containing entries for the PERIPHCONF blob based on the " + "device configuration in devicetree." + ), + ) + parser.add_argument( + "-v", + "--verbose", + default=0, + action="count", + help="Print verbose output such as debug information.", + ) + parser.add_argument( + "--soc", + type=validate_soc_choice, + required=True, + help=( + "SoC to generate PERIPHCONF macros for. " + "Used to look up soc specific hardware information" + ), + ) + parser.add_argument( + "--in-edt-pickle", + type=argparse.FileType("rb"), + required=True, + help="Path to the pickled edtlib.EDT object with devicetree contents.", + ) + parser.add_argument( + "--out-periphconf-source", + type=argparse.FileType("w", encoding="utf-8"), + required=True, + help="Path to write the generated PERIPHCONF C source file to.", + ) + return parser.parse_args() + + +def main() -> None: + args = parse_args() + dt = pickle.load(args.in_edt_pickle) + processor = dt_processor_id(dt) + lookup_tables = lookup_tables_get(Soc.soc(args.soc), Family.family(args.soc)) + builder = PeriphconfBuilder(dt, lookup_tables) + + # Application local peripherals + if processor == ProcessorId.APPLICATION: + for node in dt.label2node["cpuapp_peripherals"].children.values(): + builder.add_local_peripheral_cfg(node, **get_additional_node_kwargs(node)) + + # Radio local peripherals + if processor == ProcessorId.RADIOCORE: + for node in dt.label2node["cpurad_peripherals"].children.values(): + builder.add_local_peripheral_cfg(node, **get_additional_node_kwargs(node)) + + # Global domain peripherals + for node in dt.label2node["global_peripherals"].children.values(): + builder.add_global_peripheral_cfg(node, **get_additional_node_kwargs(node)) + + # TDD (Trace and Debug Domain) peripherals - contains coresight/TPIU + for node in dt.label2node["tdd_peripherals"].children.values(): + builder.add_global_peripheral_cfg(node, **get_additional_node_kwargs(node)) + + # Add pins referenced by 'gpios' properties on non-peripheral nodes, for example + # buttons and leds. We only add SPU configurations for these and not CTRLSEL, + # to avoid false CTRLSEL conflicts for things like PWM leds. + for node in dt.nodes: + builder.add_gpio_spu_permissions(node) + + script_name = Path(__file__).resolve().relative_to(ZEPHYR_BASE) + generated_by = f"Generated by {script_name}" + + generated_source = builder.build_generated_source(generated_by) + args.out_periphconf_source.write(generated_source) + + +def lookup_tables_get(soc: Soc, family: Family) -> SocLookupTables: + if soc == Soc.NRF54H20: + ctrlsel_lookup = { + # CAN120 + 0x5F8D_8000: { + # P2 + NrfPsel(fun=NrfFun.CAN_TX, port=2, pin=9): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.CAN_RX, port=2, pin=8): Ctrlsel.CAN_PWM_I3C, + # P9 + NrfPsel(fun=NrfFun.CAN_TX, port=9, pin=5): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.CAN_RX, port=9, pin=4): Ctrlsel.CAN, + }, + # PWM120 + 0x5F8E_4000: { + # P2 + NrfPsel(fun=NrfFun.PWM_OUT0, port=2, pin=4): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT1, port=2, pin=5): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT2, port=2, pin=6): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT3, port=2, pin=7): Ctrlsel.CAN_PWM_I3C, + # P6 + NrfPsel(fun=NrfFun.PWM_OUT0, port=6, pin=6): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT1, port=6, pin=7): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT2, port=6, pin=8): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT3, port=6, pin=9): Ctrlsel.CAN_PWM_I3C, + # P7 + NrfPsel(fun=NrfFun.PWM_OUT0, port=7, pin=0): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT1, port=7, pin=1): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT2, port=7, pin=6): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT3, port=7, pin=7): Ctrlsel.CAN_PWM_I3C, + }, + # PWM130 + 0x5F9A_4000: { + # P9 + NrfPsel(fun=NrfFun.PWM_OUT0, port=9, pin=2): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT1, port=9, pin=3): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT2, port=9, pin=4): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT3, port=9, pin=5): Ctrlsel.CAN_PWM_I3C, + }, + # SPIM130/SPIS130/TWIM130/TWIS130/UARTE130 + 0x5F9A_5000: { + # SPIM mappings + NrfPsel(fun=NrfFun.SPIM_MOSI, port=9, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=9, pin=2): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_CSN, port=9, pin=3): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=9, pin=4): Ctrlsel.SERIAL0, + # SPIS mappings + NrfPsel(fun=NrfFun.SPIS_MISO, port=9, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIS_MOSI, port=9, pin=2): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIS_CSN, port=9, pin=3): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIS_SCK, port=9, pin=4): Ctrlsel.SERIAL0, + # TWIM mappings + NrfPsel(fun=NrfFun.TWIM_SDA, port=9, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.TWIM_SCL, port=9, pin=4): Ctrlsel.SERIAL0, + # TWIS mappings + NrfPsel(fun=NrfFun.TWIS_SDA, port=9, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.TWIS_SCL, port=9, pin=4): Ctrlsel.SERIAL0, + # UARTÈ mappings + NrfPsel(fun=NrfFun.UART_TX, port=9, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RX, port=9, pin=4): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.UART_CTS, port=9, pin=2): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RTS, port=9, pin=3): Ctrlsel.SERIAL0, + }, + # SPIM131/SPIS131/TWIM131/TWIS131/UARTE131 + 0x5F9A_6000: { + # SPIM mappings + NrfPsel(fun=NrfFun.SPIM_MOSI, port=9, pin=0): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.SPIM_MISO, port=9, pin=2): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.SPIM_CSN, port=9, pin=3): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.SPIM_SCK, port=9, pin=1): Ctrlsel.CAN_TDM_SERIAL2, + # SPIS mappings + NrfPsel(fun=NrfFun.SPIS_MISO, port=9, pin=0): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.SPIS_MOSI, port=9, pin=2): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.SPIS_CSN, port=9, pin=3): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.SPIS_SCK, port=9, pin=1): Ctrlsel.CAN_TDM_SERIAL2, + # TWIM mappings + NrfPsel(fun=NrfFun.TWIM_SDA, port=9, pin=0): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TWIM_SCL, port=9, pin=1): Ctrlsel.CAN_TDM_SERIAL2, + # TWIS mappings + NrfPsel(fun=NrfFun.TWIS_SDA, port=9, pin=0): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TWIS_SCL, port=9, pin=1): Ctrlsel.CAN_TDM_SERIAL2, + # UARTÈ mappings + NrfPsel(fun=NrfFun.UART_TX, port=9, pin=0): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.UART_RX, port=9, pin=1): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_CTS, port=9, pin=2): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.UART_RTS, port=9, pin=3): Ctrlsel.CAN_TDM_SERIAL2, + }, + # VPR121 (FLPR) + 0x5F8D_4000: { + # P1 + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=8): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=9): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=10): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=11): Ctrlsel.VPR_GRC, + # P2 + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=0): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=1): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=2): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=3): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=4): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=5): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=6): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=7): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=8): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=9): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=10): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=11): Ctrlsel.VPR_GRC, + # P6 + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=0): Ctrlsel.VPR_GRC, + # (pin 1-2 are not connected with VIO) + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=3): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=4): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=5): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=6): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=7): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=8): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=9): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=10): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=11): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=12): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=6, pin=13): Ctrlsel.VPR_GRC, + # P7 + NrfPsel(fun=NrfFun.IGNORE, port=7, pin=0): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=7, pin=1): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=7, pin=2): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=7, pin=3): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=7, pin=4): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=7, pin=5): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=7, pin=6): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=7, pin=7): Ctrlsel.VPR_GRC, + # P9 + NrfPsel(fun=NrfFun.IGNORE, port=9, pin=0): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=9, pin=1): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=9, pin=2): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=9, pin=3): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=9, pin=4): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=9, pin=5): Ctrlsel.VPR_GRC, + }, + # SPIS120 + 0x5F8E_5000: { + NrfPsel(fun=NrfFun.SPIS_MISO, port=6, pin=3): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIS_MOSI, port=6, pin=4): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIS_CSN, port=6, pin=9): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIS_SCK, port=6, pin=0): Ctrlsel.SERIAL0, + }, + # SPIM120/UARTE120 + 0x5F8E_6000: { + # SPIM P6 mappings + NrfPsel(fun=NrfFun.SPIM_MOSI, port=6, pin=8): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=6, pin=7): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_CSN, port=6, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=6, pin=1): Ctrlsel.SERIAL0, + # SPIM P7 mappings + NrfPsel(fun=NrfFun.SPIM_MOSI, port=7, pin=7): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=7, pin=6): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_CSN, port=7, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=7, pin=3): Ctrlsel.SERIAL0, + # SPIM P2 mappings + NrfPsel(fun=NrfFun.SPIM_MOSI, port=2, pin=6): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=2, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_CSN, port=2, pin=7): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=2, pin=3): Ctrlsel.SERIAL0, + # UARTÈ P6 mappings + NrfPsel(fun=NrfFun.UART_TX, port=6, pin=8): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_CTS, port=6, pin=7): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RX, port=6, pin=6): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RTS, port=6, pin=5): Ctrlsel.SERIAL0, + # UARTÈ P7 mappings + NrfPsel(fun=NrfFun.UART_TX, port=7, pin=7): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_CTS, port=7, pin=6): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RX, port=7, pin=4): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RTS, port=7, pin=5): Ctrlsel.SERIAL0, + # UARTÈ P2 mappings + NrfPsel(fun=NrfFun.UART_TX, port=2, pin=6): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_CTS, port=2, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RX, port=2, pin=4): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RTS, port=2, pin=7): Ctrlsel.SERIAL0, + }, + # SPIM121 + 0x5F8E_7000: { + # SPIM P6 mappings + NrfPsel(fun=NrfFun.SPIM_MOSI, port=6, pin=13): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=6, pin=12): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_CSN, port=6, pin=10): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=6, pin=2): Ctrlsel.SERIAL0, + # SPIM P7 mappings + NrfPsel(fun=NrfFun.SPIM_MOSI, port=7, pin=1): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.SPIS_MISO, port=7, pin=1): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.SPIM_MISO, port=7, pin=0): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.SPIS_MOSI, port=7, pin=0): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.SPIM_CSN, port=7, pin=4): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.SPIS_CSN, port=7, pin=4): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.SPIM_SCK, port=7, pin=2): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.SPIS_SCK, port=7, pin=2): Ctrlsel.EXMIF_RADIO_SERIAL1, + # SPIM P2 mappings + NrfPsel(fun=NrfFun.SPIM_MOSI, port=2, pin=11): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=2, pin=10): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_CSN, port=2, pin=8): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=2, pin=2): Ctrlsel.SERIAL0, + }, + # EXMIF + 0x5F09_5000: { + NrfPsel(fun=NrfFun.EXMIF_CK, port=6, pin=0): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_RWDS, port=6, pin=2): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_CS0, port=6, pin=3): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_DQ7, port=6, pin=4): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_DQ1, port=6, pin=5): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_DQ6, port=6, pin=6): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_DQ0, port=6, pin=7): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_DQ5, port=6, pin=8): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_DQ3, port=6, pin=9): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_DQ2, port=6, pin=10): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_DQ4, port=6, pin=11): Ctrlsel.EXMIF_RADIO_SERIAL1, + NrfPsel(fun=NrfFun.EXMIF_CS1, port=6, pin=13): Ctrlsel.EXMIF_RADIO_SERIAL1, + }, + # VPR130 (PPR) + 0x5F90_8000: { + # P0 + NrfPsel(fun=NrfFun.IGNORE, port=0, pin=4): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=0, pin=5): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=0, pin=6): Ctrlsel.VPR_GRC, + NrfPsel(fun=NrfFun.IGNORE, port=0, pin=7): Ctrlsel.VPR_GRC, + }, + # TDM130 + 0x5F99_2000: { + # TDM P1 mappings + NrfPsel(fun=NrfFun.TDM_MCK, port=1, pin=2): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SCK_M, port=1, pin=3): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SCK_S, port=1, pin=3): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SDOUT, port=1, pin=4): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SDIN, port=1, pin=5): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_FSYNC_M, port=1, pin=6): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_FSYNC_S, port=1, pin=6): Ctrlsel.CAN_TDM_SERIAL2, + # TDM P2 mappings + NrfPsel(fun=NrfFun.TDM_MCK, port=2, pin=0): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SCK_M, port=2, pin=1): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SCK_S, port=2, pin=1): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SDOUT, port=2, pin=9): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SDIN, port=2, pin=10): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_FSYNC_M, port=2, pin=11): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_FSYNC_S, port=2, pin=11): Ctrlsel.CAN_TDM_SERIAL2, + }, + # TDM131 + 0x5F99_7000: { + # TDM P1 mappings + NrfPsel(fun=NrfFun.TDM_MCK, port=1, pin=0): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SCK_M, port=1, pin=1): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SCK_S, port=1, pin=1): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SDOUT, port=1, pin=9): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SDIN, port=1, pin=10): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_FSYNC_M, port=1, pin=11): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_FSYNC_S, port=1, pin=11): Ctrlsel.CAN_TDM_SERIAL2, + # TDM P2 mappings + NrfPsel(fun=NrfFun.TDM_MCK, port=2, pin=2): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SCK_M, port=2, pin=3): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SCK_S, port=2, pin=3): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SDOUT, port=2, pin=4): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_SDIN, port=2, pin=6): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_FSYNC_M, port=2, pin=7): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.TDM_FSYNC_S, port=2, pin=7): Ctrlsel.CAN_TDM_SERIAL2, + }, + # GRTC + 0x5F99_C000: { + NrfPsel(fun=NrfFun.GRTC_CLKOUT_FAST, port=1, pin=8): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.GRTC_CLKOUT_FAST, port=2, pin=5): Ctrlsel.CAN_TDM_SERIAL2, + NrfPsel(fun=NrfFun.GRTC_CLKOUT_FAST, port=9, pin=0): Ctrlsel.SERIAL0, + }, + # GPIOTE0 (RAD) + 0x5302_7000: { + # P1 + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=4): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=5): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=6): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=7): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=8): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=9): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=10): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=1, pin=11): Ctrlsel.CAN, + # P2 + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=0): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=1): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=2): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=3): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=4): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=5): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=6): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=7): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=8): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=9): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=10): Ctrlsel.CAN, + NrfPsel(fun=NrfFun.IGNORE, port=2, pin=11): Ctrlsel.CAN, + }, + # Coresight (TPIU) + 0xBF04_0000: { + NrfPsel(fun=NrfFun.TPIU_CLOCK, port=7, pin=3): Ctrlsel.TND, + NrfPsel(fun=NrfFun.TPIU_DATA0, port=7, pin=4): Ctrlsel.TND, + NrfPsel(fun=NrfFun.TPIU_DATA1, port=7, pin=5): Ctrlsel.TND, + NrfPsel(fun=NrfFun.TPIU_DATA2, port=7, pin=6): Ctrlsel.TND, + NrfPsel(fun=NrfFun.TPIU_DATA3, port=7, pin=7): Ctrlsel.TND, + }, + } + elif family == Family.SERIES_NRF92X: + ctrlsel_lookup = { + # PWM120 + 0x5F8E_4000: { + # P2 + NrfPsel(fun=NrfFun.PWM_OUT0, port=2, pin=0): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT1, port=2, pin=1): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT2, port=2, pin=2): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT3, port=2, pin=3): Ctrlsel.CAN_PWM_I3C, + # P6 + NrfPsel(fun=NrfFun.PWM_OUT0, port=6, pin=0): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT0, port=6, pin=6): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT1, port=6, pin=1): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT1, port=6, pin=7): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT2, port=6, pin=2): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT2, port=6, pin=8): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT3, port=6, pin=3): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT3, port=6, pin=9): Ctrlsel.CAN_PWM_I3C, + }, + # SPIM120/UARTE120 + 0x5F8E_6000: { + # SPIM P2 mappings + NrfPsel(fun=NrfFun.SPIM_CSN, port=2, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=2, pin=3): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MOSI, port=2, pin=4): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=2, pin=0): Ctrlsel.SERIAL0, + # SPIM P6 mappings + NrfPsel(fun=NrfFun.SPIM_CSN, port=6, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=6, pin=7): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MOSI, port=6, pin=8): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=6, pin=1): Ctrlsel.SERIAL0, + # UARTE P2 mappings + NrfPsel(fun=NrfFun.UART_CTS, port=2, pin=3): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RTS, port=2, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RX, port=2, pin=2): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_TX, port=2, pin=4): Ctrlsel.SERIAL0, + # UARTE P6 mappings + NrfPsel(fun=NrfFun.UART_CTS, port=6, pin=7): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RTS, port=6, pin=5): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RX, port=6, pin=6): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_TX, port=6, pin=8): Ctrlsel.SERIAL0, + }, + # SPIM121 + 0x5F8E_7000: { + # P2 + NrfPsel(fun=NrfFun.SPIM_CSN, port=2, pin=6): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=2, pin=8): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MOSI, port=2, pin=9): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=2, pin=1): Ctrlsel.SERIAL0, + # P6 + NrfPsel(fun=NrfFun.SPIM_CSN, port=6, pin=10): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=6, pin=12): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MOSI, port=6, pin=13): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=6, pin=2): Ctrlsel.SERIAL0, + }, + # PWM130 + 0x5F9A_4000: { + NrfPsel(fun=NrfFun.PWM_OUT0, port=9, pin=2): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT1, port=9, pin=3): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT2, port=9, pin=4): Ctrlsel.CAN_PWM_I3C, + NrfPsel(fun=NrfFun.PWM_OUT3, port=9, pin=5): Ctrlsel.CAN_PWM_I3C, + }, + # SPIM130/SPIS130/TWIM130/TWIS130/UARTE130 + 0x5F9A_5000: { + # SPIM mappings + NrfPsel(fun=NrfFun.SPIM_CSN, port=9, pin=1): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MISO, port=9, pin=2): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_MOSI, port=9, pin=3): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIM_SCK, port=9, pin=0): Ctrlsel.SERIAL0, + # SPIS mappings + NrfPsel(fun=NrfFun.SPIS_CSN, port=9, pin=1): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIS_MISO, port=9, pin=3): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIS_MOSI, port=9, pin=2): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.SPIS_SCK, port=9, pin=0): Ctrlsel.SERIAL0, + # TWIM mappings + NrfPsel(fun=NrfFun.TWIM_SCL, port=9, pin=0): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.TWIM_SDA, port=9, pin=3): Ctrlsel.SERIAL0, + # UARTE mappings + NrfPsel(fun=NrfFun.UART_CTS, port=9, pin=2): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RTS, port=9, pin=1): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_RX, port=9, pin=4): Ctrlsel.SERIAL0, + NrfPsel(fun=NrfFun.UART_TX, port=9, pin=3): Ctrlsel.SERIAL0, + }, + } + else: + raise NotImplementedError(f"No CTRLSEL table exists for soc {soc}") + + # Entries below this are common to all supported socs at the time of writing. + + adc_channel_pin_lookup = { + # SAADC + 0x5F98_2000: { + NrfSaadcChannel.AIN0: (1, 0), + NrfSaadcChannel.AIN1: (1, 1), + NrfSaadcChannel.AIN2: (1, 2), + NrfSaadcChannel.AIN3: (1, 3), + NrfSaadcChannel.AIN4: (1, 4), + NrfSaadcChannel.AIN5: (1, 5), + NrfSaadcChannel.AIN6: (1, 6), + NrfSaadcChannel.AIN7: (1, 7), + NrfSaadcChannel.AIN8: (9, 0), + NrfSaadcChannel.AIN9: (9, 1), + NrfSaadcChannel.AIN10: (9, 2), + NrfSaadcChannel.AIN11: (9, 3), + NrfSaadcChannel.AIN12: (9, 4), + NrfSaadcChannel.AIN13: (9, 5), + } + } + comp_channel_pin_lookup = { + # COMP/LPCOMP + 0x5F98_3000: { + NrfCompChannel.AIN0: (1, 0), + NrfCompChannel.AIN1: (1, 1), + NrfCompChannel.AIN2: (1, 2), + NrfCompChannel.AIN3: (1, 3), + NrfCompChannel.AIN4: (1, 4), + NrfCompChannel.AIN5: (1, 5), + NrfCompChannel.AIN6: (1, 6), + NrfCompChannel.AIN7: (1, 7), + NrfCompChannel.AIN8: (9, 0), + NrfCompChannel.AIN9: (9, 1), + } + } + spu_instances = [ + ("SPU110", 0x5F08_0000), + ("SPU111", 0x5F09_0000), + ("SPU120", 0x5F8C_0000), + ("SPU121", 0x5F8D_0000), + ("SPU122", 0x5F8E_0000), + ("SPU130", 0x5F90_0000), + ("SPU131", 0x5F92_0000), + ("SPU132", 0x5F98_0000), + ("SPU133", 0x5F99_0000), + ("SPU134", 0x5F9A_0000), + ("SPU135", 0x5F9B_0000), + ("SPU136", 0x5F9C_0000), + ("SPU137", 0x5F9D_0000), + ] + dppics = { + "DPPIC120": 0x5F8E_1000, + "DPPIC130": 0x5F92_2000, + "DPPIC131": 0x5F98_1000, + "DPPIC132": 0x5F99_1000, + "DPPIC133": 0x5F9A_1000, + "DPPIC134": 0x5F9B_1000, + "DPPIC135": 0x5F9C_1000, + "DPPIC136": 0x5F9D_1000, + } + ppib_instances = [ + ("PPIB110", 0x5F09_8000), + ("PPIB120", 0x5F8E_E000), + ("PPIB121", 0x5F8E_F000), + ("PPIB130", 0x5F92_5000), + ("PPIB131", 0x5F92_6000), + ("PPIB132", 0x5F98_D000), + ("PPIB133", 0x5F99_D000), + ("PPIB134", 0x5F9A_D000), + ("PPIB135", 0x5F9B_D000), + ("PPIB136", 0x5F9C_D000), + ("PPIB137", 0x5F9D_D000), + ] + ppib_name_to_addr = dict(ppib_instances) + dppic_to_ppib_connections = { + dppics["DPPIC120"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB121"], + channel_map=range(0, 8), + ), + dppics["DPPIC131"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB132"], + channel_map=range(0, 8), + ), + dppics["DPPIC132"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB133"], + channel_map=range(0, 8), + ), + dppics["DPPIC133"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB134"], + channel_map=range(0, 8), + ), + dppics["DPPIC134"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB135"], + channel_map=range(0, 8), + ), + dppics["DPPIC135"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB136"], + channel_map=range(0, 8), + ), + dppics["DPPIC136"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB137"], + channel_map=range(0, 8), + ), + } + ppib_to_ppib_connections = { + ppib_name_to_addr["PPIB132"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB130"], + channel_map=range(0, 8), + ), + ppib_name_to_addr["PPIB133"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB130"], + channel_map=range(8, 16), + ), + ppib_name_to_addr["PPIB134"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB130"], + channel_map=range(16, 24), + ), + ppib_name_to_addr["PPIB135"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB130"], + channel_map=range(24, 32), + ), + ppib_name_to_addr["PPIB136"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB131"], + channel_map=range(0, 8), + ), + ppib_name_to_addr["PPIB137"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB131"], + channel_map=range(8, 16), + ), + ppib_name_to_addr["PPIB121"]: FixedPPIMap( + connected_to=ppib_name_to_addr["PPIB131"], + channel_map=range(16, 24), + ), + } + return SocLookupTables( + ctrlsel_lookup=ctrlsel_lookup, + adc_channel_pin_lookup=adc_channel_pin_lookup, + comp_channel_pin_lookup=comp_channel_pin_lookup, + dppic_to_ppib_connections=dppic_to_ppib_connections, + ppib_to_ppib_connections=ppib_to_ppib_connections, + spu_instances=spu_instances, + ppib_instances=ppib_instances, + ) + + +if __name__ == "__main__": + main() diff --git a/soc/nordic/common/uicr/gen_uicr.py b/soc/nordic/common/uicr/gen_uicr.py index 78422e4312cd..8dbbc7fe5ce9 100644 --- a/soc/nordic/common/uicr/gen_uicr.py +++ b/soc/nordic/common/uicr/gen_uicr.py @@ -8,7 +8,8 @@ import argparse import ctypes as c import sys -from itertools import groupby +from itertools import groupby, pairwise +from typing import NamedTuple from elftools.elf.elffile import ELFFile from intelhex import IntelHex @@ -24,11 +25,23 @@ # Common values for representing enabled/disabled in the UICR format. ENABLED_VALUE = 0xFFFF_FFFF DISABLED_VALUE = 0xBD23_28A8 +PROTECTED_VALUE = ENABLED_VALUE # UICR_PROTECTED = UICR_ENABLED per uicr_defs.h +UNPROTECTED_VALUE = DISABLED_VALUE # Unprotected uses the default erased value + +KB_4 = 4096 class ScriptError(RuntimeError): ... +class PartitionInfo(NamedTuple): + """Information about a partition for secure storage validation.""" + + address: int + size: int + name: str + + class PeriphconfEntry(c.LittleEndianStructure): _pack_ = 1 _fields_ = [ @@ -198,6 +211,105 @@ class Uicr(c.LittleEndianStructure): ] +def validate_secure_storage_partitions(args: argparse.Namespace) -> None: + """ + Validate that secure storage partitions are laid out correctly. + + Args: + args: Parsed command line arguments containing partition information + + Raises: + ScriptError: If validation fails + """ + # Expected order: cpuapp_crypto_partition, cpurad_crypto_partition, + # cpuapp_its_partition, cpurad_its_partition + partitions = [ + PartitionInfo( + args.cpuapp_crypto_address, args.cpuapp_crypto_size, "cpuapp_crypto_partition" + ), + PartitionInfo( + args.cpurad_crypto_address, args.cpurad_crypto_size, "cpurad_crypto_partition" + ), + PartitionInfo(args.cpuapp_its_address, args.cpuapp_its_size, "cpuapp_its_partition"), + PartitionInfo(args.cpurad_its_address, args.cpurad_its_size, "cpurad_its_partition"), + ] + + # Filter out zero-sized partitions (missing partitions) + present_partitions = [p for p in partitions if p.size > 0] + + # Require at least one subpartition to be present + if not present_partitions: + raise ScriptError( + "At least one secure storage subpartition must be defined. " + "Define one or more of: cpuapp_crypto_partition, cpurad_crypto_partition, " + "cpuapp_its_partition, cpurad_its_partition" + ) + + # Check 4KB alignment for secure storage start address + if args.securestorage_address % 4096 != 0: + raise ScriptError( + f"Secure storage address {args.securestorage_address:#x} must be aligned to 4KB " + f"(4096 bytes)" + ) + + # Check 4KB alignment for secure storage size + if args.securestorage_size % 4096 != 0: + raise ScriptError( + f"Secure storage size {args.securestorage_size} bytes must be aligned to 4KB " + f"(4096 bytes)" + ) + + # Check that the first present partition starts at the secure storage address + first_partition = present_partitions[0] + if first_partition.address != args.securestorage_address: + raise ScriptError( + f"First partition {first_partition.name} starts at {first_partition.address:#x}, " + f"but must start at secure storage address {args.securestorage_address:#x}" + ) + + # Check that all present partitions have sizes that are multiples of 1KB + for partition in present_partitions: + if partition.size % 1024 != 0: + raise ScriptError( + f"Partition {partition.name} has size {partition.size} bytes, but must be " + f"a multiple of 1024 bytes (1KB)" + ) + + # Check that partitions are in correct order and don't overlap + for curr_partition, next_partition in pairwise(present_partitions): + # Check order - partitions should be in ascending address order + if curr_partition.address >= next_partition.address: + raise ScriptError( + f"Partition {curr_partition.name} (starts at {curr_partition.address:#x}) " + f"must come before {next_partition.name} (starts at {next_partition.address:#x})" + ) + + # Check for overlap + curr_end = curr_partition.address + curr_partition.size + if curr_end > next_partition.address: + raise ScriptError( + f"Partition {curr_partition.name} (ends at {curr_end:#x}) overlaps with " + f"{next_partition.name} (starts at {next_partition.address:#x})" + ) + + # Check for gaps (should be no gaps between consecutive partitions) + if curr_end < next_partition.address: + gap = next_partition.address - curr_end + raise ScriptError( + f"Gap of {gap} bytes between {curr_partition.name} (ends at {curr_end:#x}) and " + f"{next_partition.name} (starts at {next_partition.address:#x})" + ) + + # Check that combined subpartition sizes equal secure_storage_partition size + total_subpartition_size = sum(p.size for p in present_partitions) + if total_subpartition_size != args.securestorage_size: + raise ScriptError( + f"Combined size of subpartitions ({total_subpartition_size} bytes) does not match " + f"secure_storage_partition size ({args.securestorage_size} bytes). " + f"The definition is not coherent." + ) + + def main() -> None: parser = argparse.ArgumentParser( allow_abbrev=False, @@ -255,6 +367,144 @@ def main() -> None: type=lambda s: int(s, 0), help="Absolute flash address of the UICR region (decimal or 0x-prefixed hex)", ) + parser.add_argument( + "--securestorage", + action="store_true", + help="Enable secure storage support in UICR", + ) + parser.add_argument( + "--securestorage-address", + default=None, + type=lambda s: int(s, 0), + help="Absolute flash address of the secure storage partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--securestorage-size", + default=None, + type=lambda s: int(s, 0), + help="Size in bytes of the secure storage partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--cpuapp-crypto-address", + default=0, + type=lambda s: int(s, 0), + help="Absolute flash address of cpuapp_crypto_partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--cpuapp-crypto-size", + default=0, + type=lambda s: int(s, 0), + help="Size in bytes of cpuapp_crypto_partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--cpurad-crypto-address", + default=0, + type=lambda s: int(s, 0), + help="Absolute flash address of cpurad_crypto_partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--cpurad-crypto-size", + default=0, + type=lambda s: int(s, 0), + help="Size in bytes of cpurad_crypto_partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--cpuapp-its-address", + default=0, + type=lambda s: int(s, 0), + help="Absolute flash address of cpuapp_its_partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--cpuapp-its-size", + default=0, + type=lambda s: int(s, 0), + help="Size in bytes of cpuapp_its_partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--cpurad-its-address", + default=0, + type=lambda s: int(s, 0), + help="Absolute flash address of cpurad_its_partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--cpurad-its-size", + default=0, + type=lambda s: int(s, 0), + help="Size in bytes of cpurad_its_partition (decimal or 0x-prefixed hex)", + ) + parser.add_argument( + "--permit-permanently-transitioning-device-to-deployed", + action="store_true", + help=( + "Safety flag required to enable both UICR.LOCK and UICR.ERASEPROTECT together. " + "Must be explicitly provided to acknowledge permanent device state changes." + ), + ) + parser.add_argument( + "--lock", + action="store_true", + help="Enable UICR.LOCK to prevent modifications without ERASEALL", + ) + parser.add_argument( + "--eraseprotect", + action="store_true", + help="Enable UICR.ERASEPROTECT to block ERASEALL operations", + ) + parser.add_argument( + "--approtect-application-protected", + action="store_true", + help="Protect application domain access port (disable debug access)", + ) + parser.add_argument( + "--approtect-radiocore-protected", + action="store_true", + help="Protect radio core access port (disable debug access)", + ) + parser.add_argument( + "--approtect-coresight-protected", + action="store_true", + help="Protect CoreSight access port (disable debug access)", + ) + parser.add_argument( + "--protectedmem", + action="store_true", + help="Enable protected memory region in UICR", + ) + parser.add_argument( + "--protectedmem-size-bytes", + type=int, + help="Protected memory size in bytes (must be divisible by 4096)", + ) + parser.add_argument( + "--wdtstart", + action="store_true", + help="Enable watchdog timer start in UICR", + ) + parser.add_argument( + "--wdtstart-instance-code", + type=lambda s: int(s, 0), + help="Watchdog timer instance code (0xBD2328A8 for WDT0, 0x1730C77F for WDT1)", + ) + parser.add_argument( + "--wdtstart-crv", + type=int, + help="Initial Counter Reload Value (CRV) for watchdog timer (minimum: 0xF)", + ) + parser.add_argument( + "--secondary-wdtstart", + action="store_true", + help="Enable watchdog timer start in UICR.SECONDARY", + ) + parser.add_argument( + "--secondary-wdtstart-instance-code", + type=lambda s: int(s, 0), + help="Secondary watchdog timer instance code (0xBD2328A8 for WDT0, 0x1730C77F for WDT1)", + ) + parser.add_argument( + "--secondary-wdtstart-crv", + type=int, + help="Secondary initial Counter Reload Value (CRV) for watchdog timer (minimum: 0xF)", + ) parser.add_argument( "--secondary", action="store_true", @@ -266,6 +516,32 @@ def main() -> None: type=lambda s: int(s, 0), help="Absolute flash address of the secondary firmware (decimal or 0x-prefixed hex)", ) + parser.add_argument( + "--secondary-processor", + default=0xBD2328A8, + type=lambda s: int(s, 0), + help="Processor to boot for the secondary firmware ", + ) + parser.add_argument( + "--secondary-trigger", + action="store_true", + help="Enable UICR.SECONDARY.TRIGGER for automatic secondary firmware boot on reset events", + ) + parser.add_argument( + "--secondary-trigger-resetreas", + default=0, + type=lambda s: int(s, 0), + help=( + "Bitmask of reset reasons that trigger secondary firmware boot " + "(decimal or 0x-prefixed hex)" + ), + ) + parser.add_argument( + "--secondary-protectedmem-size", + default=None, + type=lambda s: int(s, 0), + help="Size in bytes of the secondary protected memory region (decimal or 0x-prefixed hex)", + ) parser.add_argument( "--secondary-periphconf-address", default=None, @@ -327,12 +603,78 @@ def main() -> None: "--out-secondary-periphconf-hex is used" ) + # Validate secure storage argument dependencies + if args.securestorage: + if args.securestorage_address is None: + raise ScriptError( + "--securestorage-address is required when --securestorage is used" + ) + if args.securestorage_size is None: + raise ScriptError("--securestorage-size is required when --securestorage is used") + + # Validate partition layout + validate_secure_storage_partitions(args) + init_values = DISABLED_VALUE.to_bytes(4, "little") * (c.sizeof(Uicr) // 4) uicr = Uicr.from_buffer_copy(init_values) uicr.VERSION.MAJOR = UICR_FORMAT_VERSION_MAJOR uicr.VERSION.MINOR = UICR_FORMAT_VERSION_MINOR + # Handle secure storage configuration + if args.securestorage: + uicr.SECURESTORAGE.ENABLE = ENABLED_VALUE + uicr.SECURESTORAGE.ADDRESS = args.securestorage_address + + # Set partition sizes in 1KB units + uicr.SECURESTORAGE.CRYPTO.APPLICATIONSIZE1KB = args.cpuapp_crypto_size // 1024 + uicr.SECURESTORAGE.CRYPTO.RADIOCORESIZE1KB = args.cpurad_crypto_size // 1024 + uicr.SECURESTORAGE.ITS.APPLICATIONSIZE1KB = args.cpuapp_its_size // 1024 + uicr.SECURESTORAGE.ITS.RADIOCORESIZE1KB = args.cpurad_its_size // 1024 + + # Handle LOCK and ERASEPROTECT configuration + # Check if both are enabled together - this requires explicit acknowledgment + if ( + args.lock + and args.eraseprotect + and not args.permit_permanently_transitioning_device_to_deployed + ): + raise ScriptError( + "Enabling both --lock and --eraseprotect requires " + "--permit-permanently-transitioning-device-to-deployed to be specified. " + "This combination permanently locks the device configuration and prevents " + "ERASEALL." + ) + + if args.lock: + uicr.LOCK = ENABLED_VALUE + if args.eraseprotect: + uicr.ERASEPROTECT = ENABLED_VALUE + # Handle APPROTECT configuration + if args.approtect_application_protected: + uicr.APPROTECT.APPLICATION = PROTECTED_VALUE + + if args.approtect_radiocore_protected: + uicr.APPROTECT.RADIOCORE = PROTECTED_VALUE + + if args.approtect_coresight_protected: + uicr.APPROTECT.CORESIGHT = PROTECTED_VALUE + # Handle protected memory configuration + if args.protectedmem: + if args.protectedmem_size_bytes % KB_4 != 0: + raise ScriptError( + f"Protected memory size ({args.protectedmem_size_bytes} bytes) " + f"must be divisible by {KB_4}" + ) + uicr.PROTECTEDMEM.ENABLE = ENABLED_VALUE + uicr.PROTECTEDMEM.SIZE4KB = args.protectedmem_size_bytes // KB_4 + + # Handle WDTSTART configuration + if args.wdtstart: + uicr.WDTSTART.ENABLE = ENABLED_VALUE + uicr.WDTSTART.CRV = args.wdtstart_crv + uicr.WDTSTART.INSTANCE = args.wdtstart_instance_code + # Process periphconf data first and configure UICR completely before creating hex objects periphconf_hex = IntelHex() secondary_periphconf_hex = IntelHex() @@ -366,7 +708,22 @@ def main() -> None: if args.secondary: uicr.SECONDARY.ENABLE = ENABLED_VALUE uicr.SECONDARY.ADDRESS = args.secondary_address + uicr.SECONDARY.PROCESSOR = args.secondary_processor + + # Handle secondary TRIGGER configuration + if args.secondary_trigger: + uicr.SECONDARY.TRIGGER.ENABLE = ENABLED_VALUE + uicr.SECONDARY.TRIGGER.RESETREAS = args.secondary_trigger_resetreas + # Handle secondary PROTECTEDMEM configuration + if args.secondary_protectedmem_size: + uicr.SECONDARY.PROTECTEDMEM.ENABLE = ENABLED_VALUE + if args.secondary_protectedmem_size % 4096 != 0: + raise ScriptError( + f"args.secondary_protectedmem_size was {args.secondary_protectedmem_size}, " + f"but must be divisible by 4096" + ) + uicr.SECONDARY.PROTECTEDMEM.SIZE4KB = args.secondary_protectedmem_size // 4096 # Handle secondary periphconf if provided if args.out_secondary_periphconf_hex: secondary_periphconf_combined = extract_and_combine_periphconfs( @@ -400,6 +757,12 @@ def main() -> None: uicr.SECONDARY.PERIPHCONF.MAXCOUNT = args.secondary_periphconf_size // 8 + # Handle secondary WDTSTART configuration + if args.secondary_wdtstart: + uicr.SECONDARY.WDTSTART.ENABLE = ENABLED_VALUE + uicr.SECONDARY.WDTSTART.CRV = args.secondary_wdtstart_crv + uicr.SECONDARY.WDTSTART.INSTANCE = args.secondary_wdtstart_instance_code + # Create UICR hex object with final UICR data uicr_hex = IntelHex() uicr_hex.frombytes(bytes(uicr), offset=args.uicr_address) @@ -426,6 +789,7 @@ def main() -> None: def extract_and_combine_periphconfs(elf_files: list[argparse.FileType]) -> bytes: combined_periphconf = [] + ipcmap_index = 0 for in_file in elf_files: elf = ELFFile(in_file) @@ -436,6 +800,7 @@ def extract_and_combine_periphconfs(elf_files: list[argparse.FileType]) -> bytes conf_section_data = conf_section.data() num_entries = len(conf_section_data) // PERIPHCONF_ENTRY_SIZE periphconf = (PeriphconfEntry * num_entries).from_buffer_copy(conf_section_data) + ipcmap_index = adjust_ipcmap_entries(periphconf, offset_index=ipcmap_index) combined_periphconf.extend(periphconf) combined_periphconf.sort(key=lambda e: e.regptr) @@ -459,5 +824,36 @@ def extract_and_combine_periphconfs(elf_files: list[argparse.FileType]) -> bytes return bytes(final_periphconf) +# This workaround is currently needed to avoid conflicts in IPCMAP whenever more than +# one image uses IPCMAP, because at the moment each image has no way of knowing which +# IPCMAP channel indices it should use for the configuration it generates locally. +# +# What the workaround does is adjust all IPCMAP entries found in the periphconf by the +# given index offset. +# +# The workaround assumes that IPCMAP entries are allocated sequentially starting from 0 +# in each image, it will probably not work for arbitrary IPCMAP entries. +def adjust_ipcmap_entries(periphconf: c.Array[PeriphconfEntry], offset_index: int) -> int: + max_ipcmap_index = offset_index + + for entry in sorted(periphconf, key=lambda e: e.regptr): + if IPCMAP_CHANNEL_START_ADDR <= entry.regptr < IPCMAP_CHANNEL_END_ADDR: + entry.regptr += offset_index * IPCMAP_CHANNEL_SIZE + entry_ipcmap_index = (entry.regptr - IPCMAP_CHANNEL_START_ADDR) // IPCMAP_CHANNEL_SIZE + max_ipcmap_index = max(max_ipcmap_index, entry_ipcmap_index) + + return max_ipcmap_index + 1 + + +# Size of each IPCMAP.CHANNEL[i] +IPCMAP_CHANNEL_SIZE = 8 +# Number of entries in IPCMAP.CHANNEL +IPCMAP_CHANNEL_COUNT = 16 +# Address of IPCMAP.CHANNEL[0] +IPCMAP_CHANNEL_START_ADDR = 0x5F92_3000 + 256 * 4 +# Address of IPCMAP.CHANNEL[channel count] + 1 +IPCMAP_CHANNEL_END_ADDR = IPCMAP_CHANNEL_START_ADDR + IPCMAP_CHANNEL_SIZE * IPCMAP_CHANNEL_COUNT + + if __name__ == "__main__": main() diff --git a/soc/nordic/common/uicr/gen_uicr/CMakeLists.txt b/soc/nordic/common/uicr/gen_uicr/CMakeLists.txt index 1163ff8e21f9..290cf16a0a6f 100644 --- a/soc/nordic/common/uicr/gen_uicr/CMakeLists.txt +++ b/soc/nordic/common/uicr/gen_uicr/CMakeLists.txt @@ -23,11 +23,19 @@ project(uicr) function(parse_kconfig_value config_file config_name output_var) file(STRINGS ${config_file} config_lines ENCODING "UTF-8") foreach(line ${config_lines}) + # Match quoted strings like CONFIG_FOO="value" if("${line}" MATCHES "^${config_name}=\"(.*)\"$") set(${output_var} "${CMAKE_MATCH_1}" PARENT_SCOPE) return() endif() + # Match unquoted values like CONFIG_FOO=y or CONFIG_FOO=n + if("${line}" MATCHES "^${config_name}=(.*)$") + set(${output_var} "${CMAKE_MATCH_1}" PARENT_SCOPE) + return() + endif() endforeach() + # If not found, return empty (including "# CONFIG_FOO is not set" case) + set(${output_var} "" PARENT_SCOPE) endfunction() # Function to compute partition absolute address and size from devicetree @@ -44,11 +52,35 @@ function(compute_partition_address_and_size partition_nodelabel output_address_v set(${output_size_var} ${partition_size} PARENT_SCOPE) endfunction() +# Function to compute optional partition address and size from devicetree +# If partition doesn't exist, sets both address and size to 0 +function(compute_optional_partition_address_and_size partition_nodelabel output_address_var output_size_var) + # Initialize with default values + set(${output_address_var} 0 PARENT_SCOPE) + set(${output_size_var} 0 PARENT_SCOPE) + + # Check if partition exists + dt_nodelabel(partition_path NODELABEL ${partition_nodelabel} QUIET) + if(partition_path) + # Call nested function with different variable names to avoid naming conflicts + compute_partition_address_and_size(${partition_nodelabel} temp_addr temp_size) + + # Copy the results to the output variables in parent scope + set(${output_address_var} ${temp_addr} PARENT_SCOPE) + set(${output_size_var} ${temp_size} PARENT_SCOPE) + endif() +endfunction() + # Use CMAKE_VERBOSE_MAKEFILE to silence an unused-variable warning. if(CMAKE_VERBOSE_MAKEFILE) endif() +set(lock_args) +set(eraseprotect_args) +set(approtect_args) +set(protectedmem_args) set(periphconf_args) +set(wdtstart_args) set(periphconf_elfs) set(merged_hex_file ${APPLICATION_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.hex) set(secondary_periphconf_elfs) @@ -60,6 +92,68 @@ set(secondary_periphconf_hex_file ${APPLICATION_BINARY_DIR}/zephyr/secondary_per dt_nodelabel(uicr_path NODELABEL "uicr" REQUIRED) dt_reg_addr(UICR_ADDRESS PATH ${uicr_path} REQUIRED) +# Handle secure storage configuration +set(securestorage_args) +if(CONFIG_GEN_UICR_SECURESTORAGE) + list(APPEND securestorage_args --securestorage) + + # Extract secure storage partition information (required) + compute_partition_address_and_size("secure_storage_partition" SECURE_STORAGE_ADDRESS SECURE_STORAGE_SIZE) + list(APPEND securestorage_args --securestorage-address ${SECURE_STORAGE_ADDRESS}) + list(APPEND securestorage_args --securestorage-size ${SECURE_STORAGE_SIZE}) + + # Extract individual partition information for validation (optional partitions) + compute_optional_partition_address_and_size("cpuapp_crypto_partition" CPUAPP_CRYPTO_ADDRESS CPUAPP_CRYPTO_SIZE) + compute_optional_partition_address_and_size("cpurad_crypto_partition" CPURAD_CRYPTO_ADDRESS CPURAD_CRYPTO_SIZE) + compute_optional_partition_address_and_size("cpuapp_its_partition" CPUAPP_ITS_ADDRESS CPUAPP_ITS_SIZE) + compute_optional_partition_address_and_size("cpurad_its_partition" CPURAD_ITS_ADDRESS CPURAD_ITS_SIZE) + + list(APPEND securestorage_args --cpuapp-crypto-address ${CPUAPP_CRYPTO_ADDRESS}) + list(APPEND securestorage_args --cpuapp-crypto-size ${CPUAPP_CRYPTO_SIZE}) + list(APPEND securestorage_args --cpurad-crypto-address ${CPURAD_CRYPTO_ADDRESS}) + list(APPEND securestorage_args --cpurad-crypto-size ${CPURAD_CRYPTO_SIZE}) + list(APPEND securestorage_args --cpuapp-its-address ${CPUAPP_ITS_ADDRESS}) + list(APPEND securestorage_args --cpuapp-its-size ${CPUAPP_ITS_SIZE}) + list(APPEND securestorage_args --cpurad-its-address ${CPURAD_ITS_ADDRESS}) + list(APPEND securestorage_args --cpurad-its-size ${CPURAD_ITS_SIZE}) +endif(CONFIG_GEN_UICR_SECURESTORAGE) + +# Handle LOCK configuration +if(CONFIG_GEN_UICR_LOCK) + list(APPEND lock_args --lock) +endif() + +# Handle ERASEPROTECT configuration +if(CONFIG_GEN_UICR_ERASEPROTECT) + list(APPEND eraseprotect_args --eraseprotect) +endif() + +# Handle APPROTECT configuration +if(CONFIG_GEN_UICR_APPROTECT_APPLICATION_PROTECTED) + list(APPEND approtect_args --approtect-application-protected) +endif() + +if(CONFIG_GEN_UICR_APPROTECT_RADIOCORE_PROTECTED) + list(APPEND approtect_args --approtect-radiocore-protected) +endif() + +if(CONFIG_GEN_UICR_APPROTECT_CORESIGHT_PROTECTED) + list(APPEND approtect_args --approtect-coresight-protected) +endif() + +# Handle protected memory configuration +if(CONFIG_GEN_UICR_PROTECTEDMEM) + list(APPEND protectedmem_args --protectedmem) + list(APPEND protectedmem_args --protectedmem-size-bytes ${CONFIG_GEN_UICR_PROTECTEDMEM_SIZE_BYTES}) +endif() + +# Handle WDTSTART configuration +if(CONFIG_GEN_UICR_WDTSTART) + list(APPEND wdtstart_args --wdtstart) + list(APPEND wdtstart_args --wdtstart-instance-code ${CONFIG_GEN_UICR_WDTSTART_INSTANCE_CODE}) + list(APPEND wdtstart_args --wdtstart-crv ${CONFIG_GEN_UICR_WDTSTART_CRV}) +endif() + if(CONFIG_GEN_UICR_GENERATE_PERIPHCONF) # gen_uicr.py parses all zephyr.elf files. To find these files (which # have not been built yet) we scan sibling build directories for @@ -79,8 +173,9 @@ if(CONFIG_GEN_UICR_GENERATE_PERIPHCONF) parse_kconfig_value(${_dir}/zephyr/.config CONFIG_KERNEL_BIN_NAME kernel_bin_name) set(kernel_elf_path ${_dir}/zephyr/${kernel_bin_name}.elf) - # Check if this is secondary firmware by looking for the marker file - if(EXISTS ${_dir}/is_secondary_firmware.txt) + # Check if this is secondary firmware by reading the Kconfig from .config + parse_kconfig_value(${_dir}/zephyr/.config CONFIG_IS_IRONSIDE_SE_SECONDARY_IMAGE is_secondary) + if(is_secondary STREQUAL "y") list(APPEND secondary_periphconf_elfs ${kernel_elf_path}) else() list(APPEND periphconf_elfs ${kernel_elf_path}) @@ -109,8 +204,49 @@ if(CONFIG_GEN_UICR_SECONDARY) list(APPEND secondary_args --secondary-address ${SECONDARY_ADDRESS} + --secondary-processor ${CONFIG_GEN_UICR_SECONDARY_PROCESSOR_VALUE} ) + # Handle secondary WDTSTART configuration + if(CONFIG_GEN_UICR_SECONDARY_WDTSTART) + list(APPEND secondary_args --secondary-wdtstart) + list(APPEND secondary_args --secondary-wdtstart-instance-code ${CONFIG_GEN_UICR_SECONDARY_WDTSTART_INSTANCE_CODE}) + list(APPEND secondary_args --secondary-wdtstart-crv ${CONFIG_GEN_UICR_SECONDARY_WDTSTART_CRV}) + endif() + + # Handle secondary TRIGGER configuration + if(CONFIG_GEN_UICR_SECONDARY_TRIGGER) + list(APPEND secondary_args --secondary-trigger) + + # Compute RESETREAS bitmask from individual trigger configs + set(resetreas_value 0) + if(CONFIG_GEN_UICR_SECONDARY_TRIGGER_APPLICATIONWDT0) + math(EXPR resetreas_value "${resetreas_value} + 0x001") + endif() + if(CONFIG_GEN_UICR_SECONDARY_TRIGGER_APPLICATIONWDT1) + math(EXPR resetreas_value "${resetreas_value} + 0x002") + endif() + if(CONFIG_GEN_UICR_SECONDARY_TRIGGER_APPLICATIONLOCKUP) + math(EXPR resetreas_value "${resetreas_value} + 0x008") + endif() + if(CONFIG_GEN_UICR_SECONDARY_TRIGGER_RADIOCOREWDT0) + math(EXPR resetreas_value "${resetreas_value} + 0x020") + endif() + if(CONFIG_GEN_UICR_SECONDARY_TRIGGER_RADIOCOREWDT1) + math(EXPR resetreas_value "${resetreas_value} + 0x040") + endif() + if(CONFIG_GEN_UICR_SECONDARY_TRIGGER_RADIOCORELOCKUP) + math(EXPR resetreas_value "${resetreas_value} + 0x100") + endif() + + list(APPEND secondary_args --secondary-trigger-resetreas ${resetreas_value}) + endif() + + # Handle secondary PROTECTEDMEM configuration + if(CONFIG_GEN_UICR_SECONDARY_PROTECTEDMEM) + list(APPEND secondary_args --secondary-protectedmem-size ${CONFIG_GEN_UICR_SECONDARY_PROTECTEDMEM_SIZE_BYTES}) + endif() + if(CONFIG_GEN_UICR_SECONDARY_GENERATE_PERIPHCONF) # Compute SECONDARY_PERIPHCONF absolute address and size from this image's devicetree compute_partition_address_and_size("secondary_periphconf_partition" SECONDARY_PERIPHCONF_ADDRESS SECONDARY_PERIPHCONF_SIZE) @@ -133,7 +269,13 @@ add_custom_command( --uicr-address ${UICR_ADDRESS} --out-merged-hex ${merged_hex_file} --out-uicr-hex ${uicr_hex_file} + ${lock_args} + ${eraseprotect_args} + ${approtect_args} + ${wdtstart_args} ${periphconf_args} + ${securestorage_args} + ${protectedmem_args} ${secondary_args} DEPENDS ${periphconf_elfs} ${secondary_periphconf_elfs} WORKING_DIRECTORY ${APPLICATION_BINARY_DIR} diff --git a/soc/nordic/common/uicr/gen_uicr/Kconfig b/soc/nordic/common/uicr/gen_uicr/Kconfig deleted file mode 100644 index 41d31db64647..000000000000 --- a/soc/nordic/common/uicr/gen_uicr/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2025 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -menu "UICR generator options" - -config GEN_UICR_GENERATE_PERIPHCONF - bool "Generate PERIPHCONF hex alongside UICR" - default y - help - When enabled, the UICR generator will populate the - periphconf_partition partition. - -config GEN_UICR_SECONDARY - bool "Enable UICR.SECONDARY.ENABLE" - -config GEN_UICR_SECONDARY_GENERATE_PERIPHCONF - bool "Generate SECONDARY.PERIPHCONF hex alongside UICR" - default y - depends on GEN_UICR_SECONDARY - help - When enabled, the UICR generator will populate the - secondary_periphconf_partition partition. - -endmenu - -source "Kconfig.zephyr" diff --git a/soc/nordic/common/uicr/gen_uicr/prj.conf b/soc/nordic/common/uicr/gen_uicr/prj.conf index b2a4ba591044..e967f3a8ee98 100644 --- a/soc/nordic/common/uicr/gen_uicr/prj.conf +++ b/soc/nordic/common/uicr/gen_uicr/prj.conf @@ -1 +1,6 @@ -# nothing here +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Enable UICR generator options - this is automatically set when building +# the gen_uicr image and enables the UICR generator configuration menu +CONFIG_IS_GEN_UICR_IMAGE=y diff --git a/soc/nordic/common/uicr/periphconf/__init__.py b/soc/nordic/common/uicr/periphconf/__init__.py new file mode 100644 index 000000000000..fe8f6fbacece --- /dev/null +++ b/soc/nordic/common/uicr/periphconf/__init__.py @@ -0,0 +1,6 @@ +""" +Copyright (c) 2025 Nordic Semiconductor ASA +SPDX-License-Identifier: Apache-2.0 +""" + +# empty diff --git a/soc/nordic/common/uicr/periphconf/builder.py b/soc/nordic/common/uicr/periphconf/builder.py new file mode 100644 index 000000000000..b8387fd9a756 --- /dev/null +++ b/soc/nordic/common/uicr/periphconf/builder.py @@ -0,0 +1,1469 @@ +""" +Copyright (c) 2025 Nordic Semiconductor ASA +SPDX-License-Identifier: Apache-2.0 +""" + +from __future__ import annotations + +import enum +import logging +import re +from collections.abc import Iterable, Iterator, Mapping +from dataclasses import dataclass +from functools import cached_property +from itertools import islice +from typing import ( + Any, + Literal, + NamedTuple, +) + +# edtlib classes used in this module. +# Defined this way as placeholders so type checking for these could be added later. +EDT = Any +Node = Any +PinCtrl = Any +Property = Any + +# Status values that indicate ownership either by the processor or a child processor +STATUS_OWNED = ("okay", "reserved") + +# Compatibles of global peripherals that should not be assigned to current core. +SKIP_SPU_PERIPH_PERM_COMPATS = { + "nordic,nrf-bellboard-tx", + "nordic,nrf-bellboard-rx", + "nordic,nrf-clic", + "nordic,nrf-dppic-global", + "nordic,nrf-gpio", + "nordic,nrf-gpiote", + "nordic,nrf-grtc", + "nordic,nrf-ipct-global", + "nordic,nrf-temp", + "nordic,nrf-vevif-task-tx", + "nordic,nrf-vevif-task-rx", + # No retention in TDD so permissions can't be set outside of the TDD service + "nordic,coresight-nrf", + "nordic,nrf-tbm", +} + +# Compatibles of global peripherals that should be assigned to the current core but do not have DMA +NO_DMA_COMPATS = { + "nordic,nrf-auxpll", + "nordic,nrf-comp", + "nordic,nrf-egu", + "nordic,nrf-exmif", + "nordic,nrf-lpcomp", + "nordic,nrf-qdec", + "nordic,nrf-timer", + "nordic,nrf-rtc", + "nordic,nrf-wdt", + # VPRs have a PERM DMASEC setting, but PPR applications currently do not work as intended when + # setting it to secure. + "nordic,nrf-vpr-coprocessor", +} + + +class BuilderError(RuntimeError): + """Generic runtime error raised by the PeriphconfBuilder""" + + ... + + +class BadDevicetreeError(BuilderError): + """Error raised when the devicetree is misconfigured + or if assumptions about the devicetree are not met. + """ + + ... + + +def _init_logger() -> logging.Logger: + formatter = logging.Formatter("{message}", style="{") + handler = logging.StreamHandler() + handler.setFormatter(formatter) + + logger = logging.getLogger("periphconf") + logger.setLevel(logging.ERROR) + logger.addHandler(handler) + + return logger + + +# Logger for the script +log = _init_logger() + + +class PeriphconfBuilder: + def __init__( + self, + dt: EDT, + lookup_tables: SocLookupTables, + ) -> None: + """Builder class used to generate a PERIPHCONF C source file based on the devicetree. + + :param dt: Devicetree object. + :param lookup_tables: Lookup table object containing soc-specific information. + """ + + self._dt = dt + self._hw_tables = lookup_tables + self._processor_id = dt_processor_id(dt) + self._owner_id = self._processor_id.default_owner_id + + self._macros = [] + self._ipcmap_idx = 0 + self._generated_ipcmaps = set() + + self._nodelabel_lookup = { + dt_reg_addr(node): node.labels[0] for node in dt.nodes if node.regs and node.labels + } + + def build_generated_source(self, header_line: str | None = None) -> str: + """Generate a C source file containing all the macros generated through + calls to the API. + """ + source_lines = [] + + if header_line: + source_lines.extend([f"/* {header_line} */", ""]) + + source_lines.extend( + [ + "#include ", + "#include ", + "", + ] + ) + + for macro in sorted(self._macros): + source_lines.append(macro.c_render(self._nodelabel_lookup)) + + return "\n".join(source_lines) + + def add_local_peripheral_cfg( + self, + node_or_nodelabel: Node | str, + /, + ) -> None: + """Generate macros for populating PERIPHCONF based on the properties of a local domain + devicetree node. + + :param node_or_nodelabel: node or label of the node to process. + """ + self._add_peripheral_cfg(node_or_nodelabel, is_global=False, add_gpios=False) + + def add_global_peripheral_cfg( + self, + node_or_nodelabel: Node | str, + /, + *, + has_irq_mapping: bool = True, + add_ppib_channel_links: bool = True, + ) -> None: + """Generate macros for populating PERIPHCONF based on the properties of the given + devicetree node located in a global domain. + + :param node_or_nodelabel: node or label of the node to process. + :param has_irq_mapping: configure IRQMAP to map the peripheral IRQs to the processor the + devicetree belongs to, if interrupts are specified on the node. + :param add_ppib_channel_links: add PPIB connections based on the channel link properties of + the node. + """ + self._add_peripheral_cfg( + node_or_nodelabel, + is_global=True, + has_irq_mapping=has_irq_mapping, + add_ppib_channel_links=add_ppib_channel_links, + ) + + def _add_peripheral_cfg( + self, + node_or_nodelabel: Node | str, + is_global: bool = True, + has_irq_mapping: bool = True, + add_ppib_channel_links: bool = True, + add_gpios: bool = True, + ) -> None: + if isinstance(node_or_nodelabel, str): + node = self._dt.label2node[node_or_nodelabel] + else: + node = node_or_nodelabel + + if node.status not in STATUS_OWNED: + return + + if is_global: + has_skip_spu_periph_perm_compat = any( + compat in SKIP_SPU_PERIPH_PERM_COMPATS for compat in node.compats + ) + if not has_skip_spu_periph_perm_compat: + has_no_dma_compat = any(compat in NO_DMA_COMPATS for compat in node.compats) + self._add_global_peripheral_spu_permissions(node, has_dma=not has_no_dma_compat) + if has_irq_mapping: + self._add_global_peripheral_irq_mapping(node) + + if "nordic,nrf-gpiote" in node.compats: + self._add_nrf_gpiote_spu_permissions(node) + + if "nordic,nrf-dppic-global" in node.compats: + self._add_nrf_dppic_spu_permissions(node) + if add_ppib_channel_links: + self._add_nrf_dppic_ppib_links(node) + + if "nordic,nrf-ipct-global" in node.compats: + self._add_nrf_ipct_global_spu_permissions(node) + self._add_nrf_ipct_ipcmap_channel_links(node) + + if "nordic,nrf-grtc" in node.compats: + self._add_nrf_grtc_spu_permissions(node) + + if "nordic,nrf-saadc" in node.compats: + self._add_nrf_saadc_channel_pin_spu_permissions(node) + + if "nordic,nrf-comp" in node.compats or "nordic,nrf-lpcomp" in node.compats: + self._add_nrf_comp_lpcomp_channel_pin_spu_permissions(node) + + self._add_peripheral_pinctrls_spu_permissions_and_ctrlsel(node) + + if "nordic,nrf-ipct-local" in node.compats: + self._add_nrf_ipct_ipcmap_channel_links(node) + + if add_gpios: + self._add_peripheral_gpios_spu_permissions_and_ctrlsel(node) + + def add_gpio_spu_permissions(self, node_or_nodelabel: Node | str, /) -> None: + """Generate macros for populating SPU FEATURE.GPIO[n].PIN[m] registers based on + gpios properties on the given devicetree node. + + CTRLSEL is not set for these properties; it is assumed that the default CTRLSEL + value (GPIO) is the correct CTRLSEL for these pins. + + :param node_or_nodelabel: node or label of the node to process. + """ + if isinstance(node_or_nodelabel, str): + node = self._dt.label2node[node_or_nodelabel] + else: + node = node_or_nodelabel + + if node.status not in STATUS_OWNED: + return + + self._add_peripheral_gpios_spu_permissions_and_ctrlsel(node, skip_ctrlsel=True) + + def _add_global_peripheral_spu_permissions( + self, + node: Node, + has_dma: bool = True, + ) -> None: + """Adds an SPU PERIPH[n].PERM entry for the peripheral described by the node.""" + addr = dt_reg_addr(node) + secure = dt_node_is_secure(node) + if has_dma: + dma_secure = secure + else: + # If there is no DMA then the DMASEC field is not writable and reads as zero. + # Set to zero to avoid readback errors. + dma_secure = False + periph_label = node.labels[0] + + spu_address = get_spu_addr_for_periph(addr) + spu_name = self._hw_tables.spu_addr_to_name[spu_address] + parsed_addr = Address(addr) + periph_slave_index = parsed_addr.slave_index + + self._macros.append( + MacroCall( + "UICR_SPU_PERIPH_PERM_SET", + [ + Address(spu_address), + periph_slave_index, + secure, + dma_secure, + self._owner_id.c_enum, + ], + comment=f"{spu_name}: {periph_label} permissions", + ) + ) + + def _add_global_peripheral_irq_mapping(self, node: Node) -> None: + """Adds an IRQMAP[n].SINK entry for each interrupt on the + peripheral described by the node. + """ + periph_identifier = dt_node_identifier(node) + get_irqn_from_dt = bool(node.labels) + + for i, interrupt in enumerate(node.interrupts): + interrupt_processors = set() + interrupt_ctrl = interrupt.controller + + interrupt_processors.update(dt_node_processors_from_labels(interrupt_ctrl)) + + if not interrupt_processors: + interrupt_processors.update(dt_node_processors_from_labels(node)) + + if not interrupt_processors: + raise BuilderError( + f"No unique processor ID could be found based on interrupt controllers " + f"or nodelabels for peripheral node {node.path}" + ) + if len(interrupt_processors) > 1: + raise BuilderError( + f"Peripheral node {node.path} corresponds to multiple processors " + f"({interrupt_processors}), which is not supported." + ) + + irq_processor = next(iter(interrupt_processors)) + + if get_irqn_from_dt: + macro_irqn = f"DT_IRQN_BY_IDX(DT_NODELABEL({node.labels[0]}), {i})" + else: + macro_irqn = str(interrupt.data["irq"]) + + self._macros.append( + MacroCall( + "UICR_IRQMAP_IRQ_SINK_SET", + [ + macro_irqn, + irq_processor.c_enum, + ], + comment=f"{periph_identifier} IRQ => {irq_processor.name}", + ) + ) + + def _add_nrf_gpiote_spu_permissions(self, node: Node) -> None: + """Adds SPU FEATURE.GPIOTE[n].CH[m] entries for configured channels on the + GPIOTE peripheral described by the node. + """ + addr = dt_reg_addr(node) + instance_name = dt_node_identifier(node) + spu_address = get_spu_addr_for_periph(addr) + spu_name = self._hw_tables.spu_addr_to_name[spu_address] + + for num, secure in dt_split_channels_get(node): + self._macros.append( + MacroCall( + "UICR_SPU_FEATURE_GPIOTE_CH_SET", + [ + Address(spu_address), + 0, + num, + secure, + self._owner_id.c_enum, + ], + comment=f"{spu_name}: {instance_name} ch. {num} permissions", + ) + ) + + def _add_nrf_dppic_spu_permissions(self, node: Node) -> None: + """Adds SPU FEATURE.DPPIC[n].CH[m] and SPU FEATURE.DPPIC[n].CHG[m] entries for + configured channels and channel groups on the DPPIC peripheral described by the node. + """ + addr = dt_reg_addr(node) + channels = dt_split_channels_get(node) + channel_groups = dt_split_channels_get( + node, + owned_name="owned-channel-groups", + nonsecure_name="nonsecure-channel-groups", + ) + + instance_name = dt_node_identifier(node) + spu_address = get_spu_addr_for_periph(addr) + spu_name = self._hw_tables.spu_addr_to_name[spu_address] + + for num, secure in channels: + self._macros.append( + MacroCall( + "UICR_SPU_FEATURE_DPPIC_CH_SET", + [ + Address(spu_address), + num, + secure, + self._owner_id.c_enum, + ], + comment=f"{spu_name}: {instance_name} ch. {num} permissions", + ) + ) + + for num, secure in channel_groups: + self._macros.append( + MacroCall( + "UICR_SPU_FEATURE_DPPIC_CHG_SET", + [ + Address(spu_address), + num, + secure, + self._owner_id.c_enum, + ], + comment=f"{spu_name}: {instance_name} ch. group {num} permissions", + ) + ) + + def _add_nrf_dppic_ppib_links(self, node: Node) -> None: + """Adds PPIB SUBSCRIBE_SEND[n] and PPIB PUBLISH_RECEIVE[n] entries for + configured "source" and "sink" channels on the DPPIC peripheral described by the node. + """ + addr = dt_reg_addr(node, secure=True) + source_channels = dt_array_prop(node, "source-channels", []) + sink_channels = dt_array_prop(node, "sink-channels", []) + + for num in source_channels: + self._link_dppi_channels(addr, num, direction="source") + + for num in sink_channels: + self._link_dppi_channels(addr, num, direction="sink") + + def _link_dppi_channels( + self, + dppic_addr: int, + channel_num: int, + direction: Literal["source"] | Literal["sink"], + ) -> None: + local_ppib_addr, local_ppib_ch_map = self._hw_tables.dppic_to_ppib_connections[dppic_addr] + local_ppib_ch = local_ppib_ch_map[channel_num] + + remote_ppib_addr, remote_ppib_ch_map = self._hw_tables.ppib_to_ppib_connections[ + local_ppib_addr + ] + remote_ppib_ch = remote_ppib_ch_map[local_ppib_ch] + + if direction == "source": + sub_ppib_addr, sub_ppib_ch = local_ppib_addr, local_ppib_ch + pub_ppib_addr, pub_ppib_ch = remote_ppib_addr, remote_ppib_ch + else: + sub_ppib_addr, sub_ppib_ch = remote_ppib_addr, remote_ppib_ch + pub_ppib_addr, pub_ppib_ch = local_ppib_addr, local_ppib_ch + + sub_ppib_name = self._hw_tables.ppib_addr_to_name[sub_ppib_addr] + pub_ppib_name = self._hw_tables.ppib_addr_to_name[pub_ppib_addr] + + self._macros.append( + MacroCall( + "UICR_PPIB_SUBSCRIBE_SEND_ENABLE", + [ + Address(sub_ppib_addr), + sub_ppib_ch, + ], + comment=( + f"SUB: {sub_ppib_name} ch. {sub_ppib_ch} => {pub_ppib_name} ch. {pub_ppib_ch}" + ), + ) + ) + self._macros.append( + MacroCall( + "UICR_PPIB_PUBLISH_RECEIVE_ENABLE", + [ + Address(pub_ppib_addr), + pub_ppib_ch, + ], + comment=( + f"PUB: {sub_ppib_name} ch. {sub_ppib_ch} => {pub_ppib_name} ch. {pub_ppib_ch}" + ), + ) + ) + + def _add_nrf_ipct_global_spu_permissions(self, node: Node) -> None: + """Adds SPU FEATURE.IPCT[n].CH[m] entries for configured channels + on the IPCT peripheral described by the node. + """ + addr = dt_reg_addr(node) + instance_name = dt_node_identifier(node) + spu_address = get_spu_addr_for_periph(addr) + spu_name = self._hw_tables.spu_addr_to_name[spu_address] + + for num, secure in dt_split_channels_get(node): + self._macros.append( + MacroCall( + "UICR_SPU_FEATURE_IPCT_CH_SET", + [ + Address(spu_address), + num, + secure, + self._owner_id.c_enum, + ], + comment=f"{spu_name}: {instance_name} ch. {num} permissions", + ) + ) + + def _add_nrf_ipct_ipcmap_channel_links(self, node: Node) -> None: + """Adds IPCMAP CHANNEL[n].SOURCE and CHANNEL[n].SINK entries for "sink" and "source" + channels on the IPCT peripheral described by the node. + """ + source_channel_links = dt_array_prop(node, "source-channel-links", []) + if len(source_channel_links) % 3 != 0: + raise BadDevicetreeError() + + sink_channel_links = dt_array_prop(node, "sink-channel-links", []) + if len(sink_channel_links) % 3 != 0: + raise BadDevicetreeError() + + node_domain_raw = dt_prop(node, "global-domain-id", None) + if node_domain_raw is None: + addr = dt_reg_addr(node) + try: + node_domain = Address(addr).domain + except ValueError as e: + raise BadDevicetreeError( + f"Failed to determine domain ID for address 0x{addr:08x} " + f"specified on node {node.path}" + ) from e + else: + node_domain = DomainId(node_domain_raw) + + for source_ch, sink_domain_raw, sink_ch in batched(source_channel_links, 3): + sink_domain = DomainId(sink_domain_raw) + self._link_ipct_channel(node_domain, source_ch, sink_domain, sink_ch) + + for sink_ch, source_domain_raw, source_ch in batched(sink_channel_links, 3): + source_domain = DomainId(source_domain_raw) + self._link_ipct_channel(source_domain, source_ch, node_domain, sink_ch) + + def _link_ipct_channel( + self, + source_domain: DomainId, + source_ch: int, + sink_domain: DomainId, + sink_ch: int, + ) -> None: + # Setting "source-channel-links" on one end and "sink-channel-links" on the other + # leads to duplicated entries without this check. + link_args = ( + source_domain.c_enum, + source_ch, + sink_domain.c_enum, + sink_ch, + ) + if link_args in self._generated_ipcmaps: + log.debug(f"Skip duplicate IPCMAP entry: {link_args}") + return + self._generated_ipcmaps.add(link_args) + + self._macros.append( + MacroCall( + "UICR_IPCMAP_CHANNEL_CFG", + [self._ipcmap_idx, *link_args], + comment=( + f"{source_domain.name} IPCT ch. {source_ch} => " + f"{sink_domain.name} IPCT ch. {sink_ch}" + ), + ) + ) + self._ipcmap_idx += 1 + + def _add_nrf_grtc_spu_permissions(self, node: Node) -> None: + """Adds SPU FEATURE.GRTC[n].CC[m] entries for configured channels + on the GRTC peripheral described by the node. + """ + grtc_addr = dt_reg_addr(node) + spu_address = get_spu_addr_for_periph(grtc_addr) + spu_name = self._hw_tables.spu_addr_to_name[spu_address] + + for num, secure in dt_split_channels_get(node): + self._macros.append( + MacroCall( + "UICR_SPU_FEATURE_GRTC_CC_SET", + [ + Address(spu_address), + num, + secure, + self._owner_id.c_enum, + ], + comment=f"{spu_name}: GRTC CC{num} permissions", + ) + ) + + def _add_peripheral_gpios_spu_permissions_and_ctrlsel( + self, + node: Node, + skip_ctrlsel: bool = False, + ) -> None: + """Adds SPU FEATURE.GPIO[n].PIN[m] and GPIO PIN_CNF[n] entries for + pins used in phandle-array properties called 'gpios' or ending in '-gpios' + found on the peripheral node. + """ + for name in node.props: + if not re.fullmatch(r"^(.+-)?gpios$", name): + continue + + if node.props[name].type != "phandle-array": + log.debug(f"skipping *-gpios prop {name} in {node.path} (not a phandle-array)") + continue + + for entry in dt_array_prop(node, name): + gpio_node = entry.controller + if "nordic,nrf-gpio" not in gpio_node.compats: + continue + + port = gpio_node.props["port"].val + num = entry.data["pin"] + secure = dt_node_is_secure(gpio_node) + if not skip_ctrlsel: + ctrlsel = self._hw_tables.lookup_ctrlsel_for_property( + node.props[name], (port, num) + ) + else: + ctrlsel = None + self._configure_gpio_pin(entry.controller, num, secure, ctrlsel) + + def _add_peripheral_pinctrls_spu_permissions_and_ctrlsel(self, node: Node) -> None: + """Adds SPU FEATURE.GPIO[n].PIN[m] and GPIO PIN_CNF[n] entries for + pins used in pinctrl properties referenced by the peripheral node. + """ + secure = dt_node_is_secure(node) + for pinctrl in node.pinctrls: + for config_node in pinctrl.conf_nodes: + for group_node in config_node.children.values(): + for i, psel_val in enumerate(dt_array_prop(group_node, "psels")): + psel = NrfPsel.from_raw(psel_val) + + if psel.is_disconnected(): + # Pin is unused and should be ignored + continue + + gpio_node = find_gpio_node_by_port( + node.edt, + psel.port, + err_suffix=f" (referenced by {group_node.path}:psels[{i}])", + ) + num = psel.pin + ctrlsel = self._hw_tables.lookup_ctrlsel_for_pinctrl(pinctrl, psel) + self._configure_gpio_pin(gpio_node, num, secure, ctrlsel) + + def _add_nrf_saadc_channel_pin_spu_permissions(self, node: Node) -> None: + """Adds SPU FEATURE.GPIO[n].PIN[m] and GPIO PIN_CNF[n] entries for + pins corresponding to the channel properties on the ADC peripheral node. + """ + saadc_addr = dt_reg_addr(node, secure=True) + if saadc_addr not in self._hw_tables.adc_channel_pin_lookup: + return + + channel_pins = self._hw_tables.adc_channel_pin_lookup[saadc_addr] + secure = dt_node_is_secure(node) + + for name, child in node.children.items(): + if not name.startswith("channel"): + continue + + for prop_name in ["zephyr,input-positive", "zephyr,input-negative"]: + prop_val = dt_prop(child, prop_name, None) + if prop_val in channel_pins: + port, num = channel_pins[prop_val] + gpio_node = find_gpio_node_by_port(node.edt, port) + self._configure_gpio_pin(gpio_node, num, secure, CTRLSEL_DEFAULT) + + def _add_nrf_comp_lpcomp_channel_pin_spu_permissions(self, node: Node) -> None: + """Adds SPU FEATURE.GPIO[n].PIN[m] and GPIO PIN_CNF[n] entries for + pins corresponding to the channel properties on the COMP/LPCOMP peripheral node. + """ + comp_addr = dt_reg_addr(node, secure=True) + if comp_addr not in self._hw_tables.comp_channel_pin_lookup: + return + + channel_pins = self._hw_tables.comp_channel_pin_lookup[comp_addr] + secure = dt_node_is_secure(node) + + for prop_name in ["psel", "extrefsel"]: + prop_val = dt_prop(node, prop_name, None) + if prop_val in channel_pins: + port, num = channel_pins[prop_val] + gpio_node = find_gpio_node_by_port(node.edt, port) + self._configure_gpio_pin(gpio_node, num, secure, CTRLSEL_DEFAULT) + + def _configure_gpio_pin( + self, + gpio_node: Node, + num: int, + secure: bool, + ctrlsel: int | None, + ) -> None: + gpio_addr = dt_reg_addr(gpio_node) + gpio_port = dt_prop(gpio_node, "port") + spu_address = get_spu_addr_for_periph(gpio_addr) + spu_name = self._hw_tables.spu_addr_to_name[spu_address] + + self._macros.append( + MacroCall( + "UICR_SPU_FEATURE_GPIO_PIN_SET", + [ + Address(spu_address), + gpio_port, + num, + secure, + self._owner_id.c_enum, + ], + comment=f"{spu_name}: P{gpio_port}.{num} permissions", + ) + ) + + if ctrlsel is not None: + ctrlsel_int = int(ctrlsel) + self._macros.append( + MacroCall( + "UICR_GPIO_PIN_CNF_CTRLSEL_SET", + [ + Address(gpio_addr), + num, + ctrlsel_int, + ], + comment=f"P{gpio_port}.{num} CTRLSEL = {ctrlsel_int}", + ) + ) + + +def find_gpio_node_by_port(dt: EDT, port: int, err_suffix: str = "") -> Node: + """Find the GPIO node in the devicetree with the given port.""" + for gpio_node in dt.compat2nodes["nordic,nrf-gpio"]: + if gpio_node.props["port"].val == port: + return gpio_node + raise BadDevicetreeError(f"Failed to find Nordic GPIO node with port {port}{err_suffix}") + + +@dataclass(order=True) +class MacroCall: + name: str + args: list + comment: str | None = None + + def c_render(self, nodelabel_lookup: dict[int, str]) -> str: + """Render the macro as C code""" + str_args = [] + for arg in self.args: + if isinstance(arg, Address): + if int(arg) in nodelabel_lookup: + str_args.append(c_dt_reg_addr_by_label(nodelabel_lookup[int(arg)])) + else: + str_args.append(c_hex_addr(int(arg))) + elif isinstance(arg, bool): + str_args.append(c_bool(arg)) + elif hasattr(arg, "c_enum"): + str_args.append(arg.c_enum) + else: + str_args.append(str(arg)) + + comment = f"/* {self.comment} */\n" if self.comment else "" + return f"{comment}{self.name}({', '.join(str_args)});" + + +def c_hex_addr(address: int) -> str: + """Format address as a C 32-bit hex literal.""" + return f"0x{address:08x}UL" + + +def c_bool(value: bool) -> str: + """Format value as a C bool literal.""" + return "true" if value else "false" + + +def c_dt_reg_addr_by_label(nodelabel: str) -> str: + """Format a peripheral address using devicetree macros to get the address based on node label""" + return f"DT_REG_ADDR(DT_NODELABEL({nodelabel}))" + + +# Equivalent to itertools.batched(), using the recipe provided in the docs. +def batched(iterable: Iterable, n: int, *, strict: bool = False) -> Iterator: + if n < 1: + raise ValueError("n must be at least one") + iterator = iter(iterable) + while batch := tuple(islice(iterator, n)): + if strict and len(batch) != n: + raise ValueError("batched(): incomplete batch") + yield batch + + +# Sentinel used to represent no provided default value in the functions below +class NoDefault: ... + + +NO_DEFAULT = NoDefault + + +def dt_reg_addr( + node: Node, + index: int = 0, + secure: bool = False, + default: int | type[NoDefault] = NO_DEFAULT, +) -> int: + """Get a register address and property identifier for a node.""" + try: + addr = node.regs[index].addr + except IndexError: + if isinstance(default, int): + addr = default + else: + raise + if secure: + return int(Address(addr).as_secure()) + return addr + + +def dt_reg_size(node: Node, index: int = 0) -> int: + """Get a register size and property identifier for a node.""" + return node.regs[index].size + + +def dt_prop(node: Node, name: str, default: Any = NO_DEFAULT) -> Any: + """Get the property value and identfier of a property. + Optionally returns a default value. + """ + try: + prop = node.props[name] + except KeyError: + if default != NO_DEFAULT: + return default + raise + + return prop.val + + +def dt_node_identifier(node: Node, default_to_path: bool = True) -> str: + """Get a string that identifies the node. + Returns the first nodelabel if it exists, otherwise defaults to the node path. + If default_to_path is False, exits with an error instead of defaulting. + """ + if node.labels: + return node.labels[0] + elif default_to_path: + return node.path + raise BuilderError(f"Expected a nodelabel on {node}, but the node has no label") + + +def dt_array_prop( + node: Node, + name: str, + default: list[Any] | type[NO_DEFAULT] = NO_DEFAULT, +) -> list[Any]: + """Get the member values and identifiers of an array property. + Optionally returns a default value. + """ + try: + prop = node.props[name] + except KeyError: + if not isinstance(default, type): + return list(default) + raise + + return list(prop.val) + + +def dt_node_processors_from_labels(node: Node) -> list[ProcessorId]: + """Deduce a processor ID from a list of devicetree nodelabels.""" + substring_processor = {cpu.zephyr_name: cpu for cpu in ProcessorId.__members__.values()} + processors = set() + for substring, processor_id in substring_processor.items(): + if any(substring in label for label in node.labels): + processors.add(processor_id) + return list(processors) + + +def dt_split_channels_get( + node: Node, + owned_name: str = "owned-channels", + nonsecure_name: str = "nonsecure-channels", +) -> list[tuple[int, bool]]: + """Parse 'split channels' properties.""" + owned = [] + owned.extend(dt_array_prop(node, owned_name, default=[])) + owned.extend(dt_array_prop(node, f"child-{owned_name}", default=[])) + + sec_lookup = {} + if nonsecure_name in node.props: + nonsecure = dt_array_prop(node, nonsecure_name) + sec_lookup.update(dict.fromkeys(nonsecure, False)) + + default_sec = dt_node_is_secure(node) + channels = [] + for ch in owned: + sec = sec_lookup.setdefault(ch, default_sec) + channels.append((ch, sec)) + + return channels + + +def dt_node_is_secure(node: Node) -> bool: + if node.bus_node is not None and node.bus_node.regs: + addr = dt_reg_addr(node.bus_node) + elif node.regs: + addr = dt_reg_addr(node) + else: + raise ValueError( + f"Failed to determine security of {node.path} " + "from the address of its bus node or itself" + ) + return Address(addr).security + + +def dt_processor_id(devicetree: EDT) -> ProcessorId: + """Get processor information from a domain's devicetree.""" + cpus = [ + node + for node in devicetree.get_node("/cpus").children.values() + if node.name.startswith("cpu@") + ] + if len(cpus) != 1: + raise RuntimeError( + f"Expected exactly 1 'cpu' node, but devicetree contained {len(cpus)} nodes" + ) + + try: + return ProcessorId(cpus[0].regs[0].addr) + except Exception as e: + raise RuntimeError( + f"Devicetree 'cpu' node has invalid Processor ID {cpus[0].regs[0].addr}" + ) from e + + +@dataclass(frozen=True) +class NrfPsel: + """Decoded NRF_PSEL values.""" + + fun: NrfFun + port: int + pin: int + + @classmethod + def from_raw(cls, psel_value: int) -> NrfPsel: + """Decode a raw NRF_PSEL encoded int value to its individual parts.""" + port, pin = divmod(psel_value & (~NRF_PSEL_FUN_MASK), NRF_PSEL_GPIO_PIN_COUNT) + fun = (psel_value & NRF_PSEL_FUN_MASK) >> NRF_PSEL_FUN_POS + return NrfPsel(fun=NrfFun(fun), port=port, pin=pin) + + def is_disconnected(self) -> bool: + """True if the value represents a disconnected pin""" + return (self.port * NRF_PSEL_GPIO_PIN_COUNT + self.pin) == NRF_PSEL_PIN_MASK + + +# # Bit position of the function bits in the pinctrl pin value encoded from NRF_PSEL() +NRF_PSEL_FUN_POS = 24 +# # Mask for the function bits in the pinctrl pin value encoded from NRF_PSEL() +NRF_PSEL_FUN_MASK = 0xFF << NRF_PSEL_FUN_POS +# Number of pins per port used in NRF_PSEL() +NRF_PSEL_GPIO_PIN_COUNT = 32 +# Mask for the port, pin bits in the pinctrl pin value encoded from NRF_PSEL() +NRF_PSEL_PIN_MASK = 0x1FF + + +@dataclass(frozen=True) +class GpiosProp: + """CTRLSEL lookup table entry for special *-gpios properties used in some peripheral + bindings, which are in some cases used instead of pinctrl. + """ + + name: str + port: int + pin: int + + +@enum.unique +class Ctrlsel(int, enum.Enum): + """ + Enumeration of GPIO.PIN_CNF[n].CTRLSEL values. + The list here may not be exhaustive. + """ + + GPIO = 0 + VPR_GRC = 1 + CAN_PWM_I3C = 2 + SERIAL0 = 3 + EXMIF_RADIO_SERIAL1 = 4 + CAN_TDM_SERIAL2 = 5 + CAN = 6 + TND = 7 + + +# Default CTRLSEL value indicating that CTRLSEL should not be used +CTRLSEL_DEFAULT = Ctrlsel.GPIO + + +class NrfFun(int, enum.Enum): + """Pin functions used with pinctrl, see include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h + Only the functions relevant for CTRLSEL deduction have been included. + """ + + UART_TX = 0 + UART_RX = 1 + UART_RTS = 2 + UART_CTS = 3 + SPIM_SCK = 4 + SPIM_MOSI = 5 + SPIM_MISO = 6 + SPIS_SCK = 7 + SPIS_MOSI = 8 + SPIS_MISO = 9 + SPIS_CSN = 10 + TWIM_SCL = 11 + TWIM_SDA = 12 + PWM_OUT0 = 22 + PWM_OUT1 = 23 + PWM_OUT2 = 24 + PWM_OUT3 = 25 + EXMIF_CK = 35 + EXMIF_DQ0 = 36 + EXMIF_DQ1 = 37 + EXMIF_DQ2 = 38 + EXMIF_DQ3 = 39 + EXMIF_DQ4 = 40 + EXMIF_DQ5 = 41 + EXMIF_DQ6 = 42 + EXMIF_DQ7 = 43 + EXMIF_CS0 = 44 + EXMIF_CS1 = 45 + CAN_TX = 46 + CAN_RX = 47 + TWIS_SCL = 48 + TWIS_SDA = 49 + EXMIF_RWDS = 50 + GRTC_CLKOUT_FAST = 55 + GRTC_CLKOUT_32K = 56 + TDM_SCK_M = 71 + TDM_SCK_S = 72 + TDM_FSYNC_M = 73 + TDM_FSYNC_S = 74 + TDM_SDIN = 75 + TDM_SDOUT = 76 + TDM_MCK = 77 + SPIM_CSN = 78 + TPIU_CLOCK = 79 + TPIU_DATA0 = 80 + TPIU_DATA1 = 81 + TPIU_DATA2 = 82 + TPIU_DATA3 = 83 + + # Value used to ignore the function field and only check (port, pin) + IGNORE = -1 + # Fallback for unknown NrfFun values, assumes that pin CTRLSEL should be set to GPIO + ASSUMED_GPIO = -2 + + @classmethod + def _missing_(cls, value: Any) -> NrfFun: + return cls.ASSUMED_GPIO + + +class NrfSaadcChannel(int, enum.Enum): + """Identifiers representing SAADC channels. + See include/zephyr/dt-bindings/adc/nrf-saadc-haltium.h. + """ + + AIN0 = 1 + AIN1 = 2 + AIN2 = 3 + AIN3 = 4 + AIN4 = 5 + AIN5 = 6 + AIN6 = 7 + AIN7 = 8 + AIN8 = 9 + AIN9 = 10 + AIN10 = 11 + AIN11 = 12 + AIN12 = 13 + AIN13 = 14 + + +class NrfCompChannel(str, enum.Enum): + """Identifiers representing COMP/LPCOMP channels. + See dts/bindings/comparator/nordic,nrf-comp.yaml. + """ + + AIN0 = "AIN0" + AIN1 = "AIN1" + AIN2 = "AIN2" + AIN3 = "AIN3" + AIN4 = "AIN4" + AIN5 = "AIN5" + AIN6 = "AIN6" + AIN7 = "AIN7" + AIN8 = "AIN8" + AIN9 = "AIN9" + + +class FixedPPIMap(NamedTuple): + """A DPPIC-PPIB or PPIB-PPIB channel mapping. + These connections are fixed in the hardware. + """ + + connected_to: int + channel_map: range + + +@dataclass +class SocLookupTables: + """Container for various hardware info needed to generate PERIPHCONF.""" + + ctrlsel_lookup: dict[int, dict[NrfPsel | GpiosProp, Ctrlsel]] + adc_channel_pin_lookup: dict[int, dict[NrfSaadcChannel, tuple[int, int]]] + comp_channel_pin_lookup: dict[int, dict[NrfCompChannel, tuple[int, int]]] + dppic_to_ppib_connections: dict[int, FixedPPIMap] + ppib_to_ppib_connections: dict[int, FixedPPIMap] + spu_instances: list[tuple[str, int]] + ppib_instances: list[tuple[str, int]] + + @cached_property + def spu_addr_to_name(self) -> Mapping[int, str]: + return {addr: name for name, addr in self.spu_instances} + + @cached_property + def ppib_addr_to_name(self) -> Mapping[int, str]: + return {addr: name for name, addr in self.ppib_instances} + + def lookup_ctrlsel_for_property(self, prop: Property, psel: tuple[int, int]) -> Ctrlsel | None: + """Find the appopriate CTRLSEL value for a given gpios property.""" + if not prop.node.regs: + # Only nodes with registers can be looked up + return None + + periph_addr = dt_reg_addr(prop.node, secure=True) + gpios_prop = GpiosProp(name=prop.name, port=psel[0], pin=psel[1]) + return self._lookup_ctrlsel(periph_addr, gpios_prop) + + def lookup_ctrlsel_for_pinctrl(self, prop: PinCtrl, psel: NrfPsel) -> Ctrlsel | None: + """Find the appopriate CTRLSEL value for a given pinctrl.""" + if psel.fun == NrfFun.ASSUMED_GPIO: + # We map unsupported values to GPIO CTRLSEL + return CTRLSEL_DEFAULT + + periph_addr = dt_reg_addr(prop.node, secure=True) + return self._lookup_ctrlsel(periph_addr, psel) + + def _lookup_ctrlsel( + self, + periph_addr: int, + prop_or_psel: NrfPsel | GpiosProp, + ) -> Ctrlsel | None: + ctrlsel = None + + if periph_addr in self.ctrlsel_lookup: + ident_lut = self.ctrlsel_lookup[periph_addr] + if prop_or_psel in ident_lut: + ctrlsel = ident_lut[prop_or_psel] + elif isinstance(prop_or_psel, NrfPsel): + # Check if this entry is enumerated with "ignored" function + sub_entry_no_fun = NrfPsel( + fun=NrfFun.IGNORE, port=prop_or_psel.port, pin=prop_or_psel.pin + ) + ctrlsel = ident_lut.get(sub_entry_no_fun, None) + + log.debug(f"periph_addr=0x{periph_addr:09_x}, {prop_or_psel=} -> {ctrlsel=}") + + return ctrlsel + + +def get_spu_addr_for_periph(periph_addr: int) -> int: + """Get the address of the SPU instance governing the permissions for the peripheral + at the given address. + """ + address = Address(periph_addr) + + # The common rule is that the SPU instance sits at the start of the address space for + # the bus of the peripheral. + address.security = True + address.slave_index = 0 + address.address_space = 0 + + # However, some buses are special due to having > 16 slaves and need special handling. + address.bus = SPU_ADDRESS_BUS_REMAPPING.get(address.bus, address.bus) + + return int(address) + + +SPU_ADDRESS_BUS_REMAPPING = { + # Both of these bus IDs represent APB32 and should use the same SPU instance with bus ID 146. + 147: 146, +} + + +@enum.unique +class DomainId(enum.IntEnum): + """Domain IDs.""" + + RESERVED = 0 + SECURE = 1 + APPLICATION = 2 + RADIOCORE = 3 + CELLCORE = 4 + GLOBALFAST = 12 + GLOBALSLOW = 13 + GLOBAL_ = 14 + GLOBAL = 15 + + @property + def c_enum(self) -> str: + return f"NRF_DOMAIN_{self.name.upper()}" + + +@enum.unique +class OwnerId(enum.IntEnum): + """Owner IDs.""" + + NONE = 0 + SECURE = 1 + APPLICATION = 2 + RADIOCORE = 3 + CELL = 4 + SYSCTRL = 8 + + @property + def c_enum(self) -> str: + return f"NRF_OWNER_{self.name.upper()}" + + +@enum.unique +class ProcessorId(enum.IntEnum): + """Processor IDs.""" + + SECURE = 1 + APPLICATION = 2 + RADIOCORE = 3 + CELLCORE = 4 + SYSCTRL = 12 + PPR = 13 + FLPR = 14 + + @property + def zephyr_name(self) -> str: + """Name used in zephyr to denote the processor with this ID.""" + match self: + case ProcessorId.SECURE: + return "cpusec" + case ProcessorId.APPLICATION: + return "cpuapp" + case ProcessorId.RADIOCORE: + return "cpurad" + case ProcessorId.CELLCORE: + return "cpucell" + case ProcessorId.SYSCTRL: + return "cpusys" + case ProcessorId.PPR: + return "cpuppr" + case ProcessorId.FLPR: + return "cpuflpr" + + @property + def default_owner_id(self) -> OwnerId: + """Default owner ID associated with this ID (the ID used by accesses from the processor).""" + match self: + case ProcessorId.SECURE: + return OwnerId.SECURE + case ProcessorId.APPLICATION: + return OwnerId.APPLICATION + case ProcessorId.RADIOCORE: + return OwnerId.RADIOCORE + case ProcessorId.CELLCORE: + return OwnerId.CELL + case ProcessorId.SYSCTRL: + return OwnerId.SYSCTRL + case ProcessorId.PPR: + return OwnerId.APPLICATION + case ProcessorId.FLPR: + return OwnerId.APPLICATION + + @property + def c_enum(self) -> str: + return f"NRF_PROCESSOR_{self.name.upper()}" + + +@enum.unique +class AddressRegion(enum.IntEnum): + """Address regions, defined by Address Format of the data sheet.""" + + PROGRAM = 0 + DATA = 1 + PERIPHERAL = 2 + EXT_XIP = 3 + EXT_XIP_ENCRYPTED = 4 + STM = 5 + CPU = 7 + + @classmethod + def from_address(cls, address: int) -> AddressRegion: + """Get the address region of an address.""" + return Address(address).region + + +# Regions that have domain ID and security fields +HAS_DOMAIN_SECURITY = [ + AddressRegion.PROGRAM, + AddressRegion.DATA, + AddressRegion.PERIPHERAL, + AddressRegion.STM, +] + +# Regions that have the peripheral address format +HAS_PERIPH_BITS = [ + AddressRegion.PERIPHERAL, + AddressRegion.STM, +] + + +class Address: + """Helper for working with addresses.""" + + def __init__(self, value: int | Address = 0) -> None: + self._val = int(value) + + def __repr__(self) -> str: + if self.region in HAS_DOMAIN_SECURITY: + domain_sec_str = ( + f", domain={self.domain.name} ({int(self.domain)}), security={self.security}" + ) + else: + domain_sec_str = "" + + if self.region in HAS_PERIPH_BITS: + periph_bits_str = ( + f", bus={self.bus} (0b{self.bus:09_b}), " + f"slave_index={self.slave_index} (0b{self.slave_index:09_b})" + ) + else: + periph_bits_str = "" + + field_str = ( + f"region={self.region.name} ({int(self.region)}){domain_sec_str}{periph_bits_str}, " + f"address_space=0x{self.address_space:_x}" + ) + + return f"{type(self).__name__}({field_str})" + + def __str__(self) -> str: + return repr(self) + + def as_secure(self) -> Address: + addr = Address(self) + addr.security = True + return addr + + @property + def region(self) -> AddressRegion: + """Address region.""" + return AddressRegion(get_field(self._val, ADDRESS_REGION_POS, ADDRESS_REGION_MASK)) + + @region.setter + def region(self, new: int) -> None: + self._val = update_field(self._val, new, ADDRESS_REGION_POS, ADDRESS_REGION_MASK) + + @property + def security(self) -> bool: + """Address security (only present in some regions).""" + self._check_has_security() + return bool(get_field(self._val, ADDRESS_SECURITY_POS, ADDRESS_SECURITY_MASK)) + + @security.setter + def security(self, new: bool) -> None: + self._check_has_security() + self._val = update_field(self._val, int(new), ADDRESS_SECURITY_POS, ADDRESS_SECURITY_MASK) + + def _check_has_security(self) -> None: + self._check_region_has_field(HAS_DOMAIN_SECURITY, "security bit") + + @property + def domain(self) -> DomainId: + """Address domain ID (only present in some regions).""" + self._check_has_domain_id() + return DomainId(get_field(self._val, ADDRESS_DOMAIN_POS, ADDRESS_DOMAIN_MASK)) + + @domain.setter + def domain(self, new: DomainId | int) -> None: + self._check_has_domain_id() + self._val = update_field(self._val, new, ADDRESS_DOMAIN_POS, ADDRESS_DOMAIN_MASK) + + def _check_has_domain_id(self) -> None: + self._check_region_has_field(HAS_DOMAIN_SECURITY, "domain ID") + + @property + def bus(self) -> int: + """Bus ID (only present in some regions).""" + self._check_has_bus() + return get_field(self._val, ADDRESS_BUS_POS, ADDRESS_BUS_MASK) + + @bus.setter + def bus(self, new: int) -> None: + self._check_has_bus() + self._val = update_field(self._val, new, ADDRESS_BUS_POS, ADDRESS_BUS_MASK) + + def _check_has_bus(self) -> None: + self._check_region_has_field(HAS_PERIPH_BITS, "Peripheral/APB bus number") + + @property + def slave_index(self) -> int: + """Slave index (only present in some regions).""" + self._check_has_slave_index() + return get_field(self._val, ADDRESS_SLAVE_POS, ADDRESS_SLAVE_MASK) + + @slave_index.setter + def slave_index(self, new: int) -> None: + self._check_has_slave_index() + self._val = update_field(self._val, new, ADDRESS_SLAVE_POS, ADDRESS_SLAVE_MASK) + + def _check_has_slave_index(self) -> None: + self._check_region_has_field(HAS_PERIPH_BITS, "Peripheral/APB slave index") + + @property + def address_space(self) -> int: + """Internal address space address (semantics depend on the region).""" + match self.region: + case AddressRegion.PROGRAM | AddressRegion.DATA: + return get_field(self._val, ADDRESS_SPACE_POS, ADDRESS_PROGRAM_DATA_SPACE_MASK) + case AddressRegion.PERIPHERAL | AddressRegion.STM: + return get_field(self._val, ADDRESS_SPACE_POS, ADDRESS_PERIPHERAL_SPACE_MASK) + case _: + return get_field(self._val, ADDRESS_SPACE_POS, ADDRESS_DEFAULT_SPACE_MASK) + + @address_space.setter + def address_space(self, new: int) -> None: + match self.region: + case AddressRegion.PROGRAM | AddressRegion.DATA: + self._val = update_field( + self._val, new, ADDRESS_SPACE_POS, ADDRESS_PROGRAM_DATA_SPACE_MASK + ) + case AddressRegion.PERIPHERAL | AddressRegion.STM: + self._val = update_field( + self._val, new, ADDRESS_SPACE_POS, ADDRESS_PERIPHERAL_SPACE_MASK + ) + case _: + self._val = update_field( + self._val, new, ADDRESS_SPACE_POS, ADDRESS_DEFAULT_SPACE_MASK + ) + + def _check_region_has_field(self, valid_regions: list[AddressRegion], field_name: str) -> None: + if self.region not in valid_regions: + raise ValueError(f"{field_name} is not defined for address region {self.region.name}") + + def __eq__(self, other) -> bool: + return int(self) == int(other) + + def __lt__(self, other: Address | int) -> bool: + return int(self) < int(other) + + def __int__(self) -> int: + return self._val + + +ADDRESS_REGION_POS = 29 +ADDRESS_REGION_MASK = 0x7 << ADDRESS_REGION_POS +ADDRESS_SECURITY_POS = 28 +ADDRESS_SECURITY_MASK = 0x1 << ADDRESS_SECURITY_POS +ADDRESS_DOMAIN_POS = 24 +ADDRESS_DOMAIN_MASK = 0xF << ADDRESS_DOMAIN_POS +ADDRESS_BUS_POS = 16 +ADDRESS_BUS_MASK = 0xFF << ADDRESS_BUS_POS +ADDRESS_SLAVE_POS = 12 +ADDRESS_SLAVE_MASK = 0xF << ADDRESS_SLAVE_POS +ADDRESS_PERIPHID_POS = 12 +ADDRESS_PERIPHID_MASK = 0x7FF << ADDRESS_PERIPHID_POS +ADDRESS_SPACE_POS = 0 +ADDRESS_PROGRAM_DATA_SPACE_MASK = 0xFF_FFFF +ADDRESS_PERIPHERAL_SPACE_MASK = 0xFFF +ADDRESS_DEFAULT_SPACE_MASK = 0x1FFF_FFFF + + +def peripheral_id_get(periph_address: int) -> int: + """Get the peripheral ID of a peripheral address.""" + return get_field(periph_address, ADDRESS_PERIPHID_POS, ADDRESS_PERIPHID_MASK) + + +def get_field(value: int, field_pos: int, field_mask: int) -> int: + """Get the value of a field in a bitfield.""" + return (value & field_mask) >> field_pos + + +def update_field(value: int, field_new: int, field_pos: int, field_mask: int) -> int: + """Update a field in a bitfield.""" + return (value & ~field_mask) | ((field_new << field_pos) & field_mask) diff --git a/soc/nordic/common/uicr/sysbuild.cmake b/soc/nordic/common/uicr/sysbuild.cmake index 167ac7c64a2d..fb797b6b76ee 100644 --- a/soc/nordic/common/uicr/sysbuild.cmake +++ b/soc/nordic/common/uicr/sysbuild.cmake @@ -8,4 +8,24 @@ ExternalZephyrProject_Add( # Ensure UICR is configured and built after the default image so EDT/ELFs exist. sysbuild_add_dependencies(CONFIGURE uicr ${DEFAULT_IMAGE}) -add_dependencies(uicr ${DEFAULT_IMAGE}) + +# Add build dependencies for all images whose ELF files may be used by gen_uicr. +# The gen_uicr/CMakeLists.txt scans all sibling build directories and adds their +# ELF files as file dependencies. However, we also need target dependencies to +# ensure those images are built before uicr attempts to use their ELF files. +# +# Use cmake_language(DEFER DIRECTORY) to ensure this runs after ALL images have +# been added to the sysbuild_images global property, even if some module adds +# images after the soc subdirectory is processed. We defer to the source root +# directory to ensure we're at the top-level scope where all subdirectories have +# completed processing. +function(uicr_add_image_dependencies) + get_property(all_images GLOBAL PROPERTY sysbuild_images) + foreach(img ${all_images}) + if(NOT img STREQUAL "uicr") + add_dependencies(uicr ${img}) + endif() + endforeach() +endfunction() + +cmake_language(DEFER DIRECTORY ${CMAKE_SOURCE_DIR} CALL uicr_add_image_dependencies) diff --git a/soc/nordic/ironside/Kconfig b/soc/nordic/ironside/Kconfig index ce4878b7b182..32c6ef38165f 100644 --- a/soc/nordic/ironside/Kconfig +++ b/soc/nordic/ironside/Kconfig @@ -76,7 +76,7 @@ config NRF_IRONSIDE_ABB_STATUSANA_CHECK_MAX_ATTEMPTS range 0 255 default 50 help - Maximum attempts with 10us intervals before busy status will be reported. + Maximum timeout when waiting for DVFS oppoint change mutex lock. endif # NRF_IRONSIDE_DVFS_SERVICE diff --git a/soc/nordic/ironside/include/nrf_ironside/boot_report.h b/soc/nordic/ironside/include/nrf_ironside/boot_report.h index c4d31c9dbc59..8c602c00134c 100644 --- a/soc/nordic/ironside/include/nrf_ironside/boot_report.h +++ b/soc/nordic/ironside/include/nrf_ironside/boot_report.h @@ -116,6 +116,8 @@ #define IRONSIDE_BOOT_REPORT_LOCAL_DOMAIN_CONTEXT_SIZE (16UL) /** Length of the random data buffer in bytes. */ #define IRONSIDE_BOOT_REPORT_RANDOM_DATA_SIZE (32UL) +/** Length of the uuid buffer in bytes. */ +#define IRONSIDE_BOOT_REPORT_UUID_SIZE (16UL) /** @brief Initialization/boot status description contained in the boot report. */ struct ironside_boot_report_init_status { @@ -207,8 +209,10 @@ struct ironside_boot_report { struct ironside_boot_report_init_context init_context; /** CSPRNG data */ uint8_t random_data[IRONSIDE_BOOT_REPORT_RANDOM_DATA_SIZE]; + /** Device Info data : 128-bit Universally Unique IDentifier (UUID) */ + uint8_t device_info_uuid[IRONSIDE_BOOT_REPORT_UUID_SIZE]; /** Reserved for Future Use */ - uint32_t rfu2[64]; + uint32_t rfu2[60]; }; /** diff --git a/soc/nordic/ironside/include/nrf_ironside/update.h b/soc/nordic/ironside/include/nrf_ironside/update.h index b01b5df6dadb..6e520e4e680b 100644 --- a/soc/nordic/ironside/include/nrf_ironside/update.h +++ b/soc/nordic/ironside/include/nrf_ironside/update.h @@ -18,11 +18,27 @@ #define IRONSIDE_UPDATE_ERROR_NOT_PERMITTED (1) /** Failed to write the update metadata to SICR. */ #define IRONSIDE_UPDATE_ERROR_SICR_WRITE_FAILED (2) +/** Update candidate is placed outside of valid range */ +#define IRONSIDE_UPDATE_ERROR_INVALID_ADDRESS (3) /** * @} */ +/** Size of the update blob */ +#ifdef CONFIG_SOC_SERIES_NRF54HX +#define IRONSIDE_UPDATE_BLOB_SIZE (160 * 1024) +#elif CONFIG_SOC_SERIES_NRF92X +#define IRONSIDE_UPDATE_BLOB_SIZE (160 * 1024) +#else +#error "Missing update blob size" +#endif + +/** Min address used for storing the update candidate */ +#define IRONSIDE_UPDATE_MIN_ADDRESS (0x0e100000) +/** Max address used for storing the update candidate */ +#define IRONSIDE_UPDATE_MAX_ADDRESS (0x0e200000 - IRONSIDE_UPDATE_BLOB_SIZE) + /** Length of the update manifest in bytes */ #define IRONSIDE_UPDATE_MANIFEST_LENGTH (256) /** Length of the update public key in bytes. */ @@ -62,6 +78,8 @@ struct ironside_update_blob { * @param update Pointer to update blob * * @retval 0 on a successful request (although the update itself may still fail). + * @retval -IRONSIDE_UPDATE_ERROR_INVALID_ADDRESS if the address of the update is outside of the + * accepted range. * @retval -IRONSIDE_UPDATE_ERROR_NOT_PERMITTED if missing access to the update candidate. * @retval -IRONSIDE_UPDATE_ERROR_SICR_WRITE_FAILED if writing update parameters to SICR failed. * @retval Positive error status if reported by IronSide call (see error codes in @ref call.h). diff --git a/soc/nordic/ironside/update.c b/soc/nordic/ironside/update.c index a56407a3fa14..fabf6fb01049 100644 --- a/soc/nordic/ironside/update.c +++ b/soc/nordic/ironside/update.c @@ -11,6 +11,11 @@ int ironside_update(const struct ironside_update_blob *update) int err; struct ironside_call_buf *const buf = ironside_call_alloc(); + if ((uintptr_t)update < IRONSIDE_UPDATE_MIN_ADDRESS || + (uintptr_t)update > IRONSIDE_UPDATE_MAX_ADDRESS) { + return -IRONSIDE_UPDATE_ERROR_INVALID_ADDRESS; + } + buf->id = IRONSIDE_CALL_ID_UPDATE_SERVICE_V0; buf->args[IRONSIDE_UPDATE_SERVICE_UPDATE_PTR_IDX] = (uintptr_t)update; diff --git a/soc/nordic/nrf53/Kconfig b/soc/nordic/nrf53/Kconfig index 7260d5c7d66d..6e53dc277c65 100644 --- a/soc/nordic/nrf53/Kconfig +++ b/soc/nordic/nrf53/Kconfig @@ -167,12 +167,32 @@ config NRF_SPU_FLASH_REGION_SIZE help FLASH region size for the NRF_SPU peripheral +config NRF_TRUSTZONE_FLASH_REGION_SIZE + hex + default NRF_SPU_FLASH_REGION_SIZE + help + Define the flash region size from a TrustZone perspective. + This is used when we set the security attributes(S/NSC/NS) of a region + in TrustZone enabled devices. + In practice this option defines the granularity of the security attributes, + i.e. the smallest region that can be set to secure or non-secure. + config NRF_SPU_RAM_REGION_SIZE hex default 0x2000 help RAM region size for the NRF_SPU peripheral +config NRF_TRUSTZONE_RAM_REGION_SIZE + hex + default NRF_SPU_RAM_REGION_SIZE + help + Define the RAM region size from a TrustZone perspective. + This is used when we set the security attributes(S/NSC/NS) of a region + in TrustZone enabled devices. + In practice this option defines the granularity of the security attributes, + i.e. the smallest region that can be set to secure or non-secure. + config SOC_NRF_GPIO_FORWARDER_FOR_NRF5340 bool "Forward GPIO pins to network core" depends on NRF_SOC_SECURE_SUPPORTED diff --git a/soc/nordic/nrf54h/CMakeLists.txt b/soc/nordic/nrf54h/CMakeLists.txt index 94e38e62f2b1..25e4796a4169 100644 --- a/soc/nordic/nrf54h/CMakeLists.txt +++ b/soc/nordic/nrf54h/CMakeLists.txt @@ -5,10 +5,17 @@ if(CONFIG_ARM) zephyr_library_sources(soc.c) if(CONFIG_PM OR CONFIG_POWEROFF) zephyr_library_sources(power.c) + zephyr_code_relocate( + FILES power.c + FILTER ".*\\.cache_retain_and_sleep" + LOCATION PMLocalRamfunc_TEXT + ) endif() endif() -zephyr_library_sources_ifdef(CONFIG_PM_S2RAM pm_s2ram.c) +if(NOT CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE) + zephyr_library_sources_ifdef(CONFIG_PM_S2RAM pm_s2ram.c) +endif() zephyr_include_directories(.) diff --git a/soc/nordic/nrf54h/Kconfig b/soc/nordic/nrf54h/Kconfig index de88045d32fb..f07a620ccdb3 100644 --- a/soc/nordic/nrf54h/Kconfig +++ b/soc/nordic/nrf54h/Kconfig @@ -35,6 +35,7 @@ config SOC_NRF54H20_CPUAPP_COMMON select NRFS_HAS_TEMP_SERVICE select NRFS_HAS_VBUS_DETECTOR_SERVICE select HAS_PM + select HAS_PM_S2RAM_CUSTOM_MARKING select HAS_POWEROFF config SOC_NRF54H20_CPUAPP @@ -66,17 +67,6 @@ config SOC_NRF54H20_CPURAD_COMMON select HAS_PM select HAS_POWEROFF -config SOC_NRF54H20_TDD_ENABLE - bool "Power and configure the trace and debug domain (TDD)" - depends on SOC_NRF54H20_CPUAPP - select NRF_IRONSIDE_TDD_SERVICE - select SOC_LATE_INIT_HOOK - help - This will at application boot time request that the trace and - debug domain (TDD) is powered up and configured. - This allows configuring the coresight peripherals from - the application domain. - config SOC_NRF54H20_CPURAD_ENABLE bool "Boot the nRF54H20 Radio core" default y if NRF_802154_SER_HOST || BT_HCI_HOST @@ -105,6 +95,16 @@ config SOC_NRF54H20_CPURAD_ENABLE_DEBUG_WAIT endif # SOC_NRF54H20_CPURAD_ENABLE +config SOC_NRF54H20_DISABLE_ALL_GPIO_RETENTION_WORKAROUND + bool "Disable all GPIO pin retention on boot" + default y + depends on SOC_NRF54H20_CPUAPP || SOC_NRF54H20_CPURAD + +config SOC_NRF54H20_PM_S2RAM_OVERRIDE + bool "Override `pm_s2ram` implementation" + help + Override Nordic s2ram implementation. + config SOC_NRF54H20_CPURAD select SOC_NRF54H20_CPURAD_COMMON diff --git a/soc/nordic/nrf54h/Kconfig.defconfig b/soc/nordic/nrf54h/Kconfig.defconfig index a1b7961f3007..3e4c61810984 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig +++ b/soc/nordic/nrf54h/Kconfig.defconfig @@ -40,6 +40,13 @@ if PM config PM_DEVICE default y +if LOG + +config LOG_PROCESS_THREAD_STACK_SIZE + default 1536 + +endif # LOG + endif # PM if PM_DEVICE diff --git a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp index 0cdc22760405..86149e5bd0e0 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp +++ b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp @@ -9,9 +9,12 @@ config NUM_IRQS default 471 config SHELL_BACKEND_SERIAL - default n if NRF_ETR_SHELL + default n if DEBUG_NRF_ETR_SHELL config POWER_DOMAIN default y +config CODE_DATA_RELOCATION + default y if (PM || POWEROFF) && !MCUBOOT + endif # SOC_NRF54H20_CPUAPP diff --git a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad index b3f5216c8f9f..31687c2a5443 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad +++ b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad @@ -14,4 +14,7 @@ config PM config POWER_DOMAIN default y +config CODE_DATA_RELOCATION + default y if PM || POWEROFF + endif # SOC_NRF54H20_CPURAD diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index 221293c5b82e..768233b2ac8b 100644 --- a/soc/nordic/nrf54h/pm_s2ram.c +++ b/soc/nordic/nrf54h/pm_s2ram.c @@ -76,7 +76,9 @@ typedef struct { struct backup { _nvic_context_t nvic_context; +#if defined(CONFIG_MPU) _mpu_context_t mpu_context; +#endif _scb_context_t scb_context; #if defined(CONFIG_FPU) && !defined(CONFIG_FPU_SHARING) _fpu_context_t fpu_context; @@ -88,6 +90,7 @@ static __noinit struct backup backup_data; extern void z_arm_configure_static_mpu_regions(void); extern int z_arm_mpu_init(void); +#if defined(CONFIG_MPU) /* MPU registers cannot be simply copied because content of RBARx RLARx registers * depends on region which is selected by RNR register. */ @@ -130,6 +133,7 @@ static void mpu_restore(_mpu_context_t *backup) MPU->RNR = rnr; MPU->CTRL = backup->CTRL; } +#endif /* defined(CONFIG_MPU) */ static void nvic_save(_nvic_context_t *backup) { @@ -219,10 +223,24 @@ static void fpu_restore(_fpu_context_t *backup) #endif /* !defined(CONFIG_FPU_SHARING) */ #endif /* defined(CONFIG_FPU) */ +#if DT_NODE_EXISTS(DT_NODELABEL(mcuboot_s2ram)) &&\ + DT_NODE_HAS_COMPAT(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region) +/* Linker section name is given by `zephyr,memory-region` property of + * `zephyr,memory-region` compatible DT node with nodelabel `mcuboot_s2ram`. + */ +__attribute__((section(DT_PROP(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region)))) +volatile struct mcuboot_resume_s _mcuboot_resume; + +#define SET_MCUBOOT_RESUME_MAGIC() _mcuboot_resume.magic = MCUBOOT_S2RAM_RESUME_MAGIC +#else +#define SET_MCUBOOT_RESUME_MAGIC() +#endif + int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) { int ret; + SET_MCUBOOT_RESUME_MAGIC(); scb_save(&backup_data.scb_context); #if defined(CONFIG_FPU) #if !defined(CONFIG_FPU_SHARING) @@ -231,7 +249,9 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) fpu_power_down(); #endif nvic_save(&backup_data.nvic_context); +#if defined(CONFIG_MPU) mpu_save(&backup_data.mpu_context); +#endif ret = arch_pm_s2ram_suspend(system_off); /* Cache and FPU are powered down so power up is needed even if s2ram failed. */ nrf_power_up_cache(); @@ -246,7 +266,9 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) return ret; } +#if defined(CONFIG_MPU) mpu_restore(&backup_data.mpu_context); +#endif nvic_restore(&backup_data.nvic_context); scb_restore(&backup_data.scb_context); diff --git a/soc/nordic/nrf54h/pm_s2ram.h b/soc/nordic/nrf54h/pm_s2ram.h index 565afad6ca10..01c098ea4310 100644 --- a/soc/nordic/nrf54h/pm_s2ram.h +++ b/soc/nordic/nrf54h/pm_s2ram.h @@ -10,6 +10,13 @@ #ifndef _ZEPHYR_SOC_ARM_NORDIC_NRF_PM_S2RAM_H_ #define _ZEPHYR_SOC_ARM_NORDIC_NRF_PM_S2RAM_H_ +#define MCUBOOT_S2RAM_RESUME_MAGIC 0x75832419 + +struct mcuboot_resume_s { + uint32_t magic; /* magic value to identify valid structure */ + uint32_t slot_info; +}; + /** * @brief Save CPU state on suspend * diff --git a/soc/nordic/nrf54h/power.c b/soc/nordic/nrf54h/power.c index e1263be0d0e5..c72cb6e834e5 100644 --- a/soc/nordic/nrf54h/power.c +++ b/soc/nordic/nrf54h/power.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -87,18 +88,48 @@ void nrf_poweroff(void) CODE_UNREACHABLE; } -static void s2idle_enter(uint8_t substate_id) +#if CONFIG_MCUBOOT +static __ramfunc +#else +static __attribute__((__used__, noinline)) +#endif +void cache_retain_and_sleep(void) +{ + nrf_cache_task_trigger(NRF_DCACHE, NRF_CACHE_TASK_SAVE); + nrf_cache_task_trigger(NRF_ICACHE, NRF_CACHE_TASK_SAVE); + while (nrf_cache_busy_check(NRF_DCACHE) || + nrf_cache_busy_check(NRF_ICACHE)) { + + } + + __set_BASEPRI(0); + __ISB(); + __DSB(); + __WFI(); + + nrf_cache_task_trigger(NRF_ICACHE, NRF_CACHE_TASK_RESTORE); + nrf_cache_task_trigger(NRF_DCACHE, NRF_CACHE_TASK_RESTORE); + while (nrf_cache_busy_check(NRF_DCACHE) || + nrf_cache_busy_check(NRF_ICACHE)) { + + } +} + +void s2idle_enter(uint8_t substate_id) { +#if !defined(CONFIG_SOC_NRF54H20_CPURAD) + soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_MAIN); +#endif switch (substate_id) { case 0: /* Substate for idle with cache powered on - not implemented yet. */ break; - case 1: /* Substate for idle with cache retained - not implemented yet. */ - break; + case 1: /* Substate for idle with cache retained. */ + soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0); + nrf_soc_memconf_retain_set(true); + cache_retain_and_sleep(); + return; case 2: /* Substate for idle with cache disabled. */ -#if !defined(CONFIG_SOC_NRF54H20_CPURAD) - soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_MAIN); -#endif common_suspend(); break; default: /* Unknown substate. */ @@ -117,17 +148,19 @@ static void s2idle_exit(uint8_t substate_id) case 0: /* Substate for idle with cache powered on - not implemented yet. */ break; - case 1: /* Substate for idle with cache retained - not implemented yet. */ + case 1: /* Substate for idle with cache retained. */ + nrf_soc_memconf_retain_set(false); break; case 2: /* Substate for idle with cache disabled. */ nrf_power_up_cache(); - common_resume(); -#if !defined(CONFIG_SOC_NRF54H20_CPURAD) - soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_MAIN); -#endif + break; default: /* Unknown substate. */ return; } + common_resume(); +#if !defined(CONFIG_SOC_NRF54H20_CPURAD) + soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_MAIN); +#endif } #if defined(CONFIG_PM_S2RAM) diff --git a/soc/nordic/nrf54h/soc.c b/soc/nordic/nrf54h/soc.c index 01cacf48f62f..c291767d0906 100644 --- a/soc/nordic/nrf54h/soc.c +++ b/soc/nordic/nrf54h/soc.c @@ -14,6 +14,7 @@ #include #endif +#include #include #include #include @@ -22,14 +23,10 @@ #include #include #include -#include #if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) #include #endif -#if defined(CONFIG_SOC_NRF54H20_TDD_ENABLE) -#include -#endif LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); @@ -39,6 +36,12 @@ LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); #define HSFLL_NODE DT_NODELABEL(cpurad_hsfll) #endif +#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)))))) + #ifdef CONFIG_USE_DT_CODE_PARTITION #define FLASH_LOAD_OFFSET DT_REG_ADDR(DT_CHOSEN(zephyr_code_partition)) #elif defined(CONFIG_FLASH_LOAD_OFFSET) @@ -46,7 +49,8 @@ LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); #endif #define PARTITION_IS_RUNNING_APP_PARTITION(label) \ - (DT_REG_ADDR(DT_NODELABEL(label)) == FLASH_LOAD_OFFSET) + (DT_REG_ADDR(DT_NODELABEL(label)) <= FLASH_LOAD_OFFSET && \ + DT_REG_ADDR(DT_NODELABEL(label)) + DT_REG_SIZE(DT_NODELABEL(label)) > FLASH_LOAD_OFFSET) sys_snode_t soc_node; @@ -60,6 +64,26 @@ sys_snode_t soc_node; ADDRESS_DOMAIN_Msk | \ ADDRESS_BUS_Msk))) +void nrf_soc_memconf_retain_set(bool enable) +{ + uint32_t ret_mask = BIT(RAMBLOCK_RET_BIT_ICACHE) | BIT(RAMBLOCK_RET_BIT_DCACHE); + + nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 0, ret_mask, enable); + nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 1, ret_mask, enable); + +#if defined(RAMBLOCK_RET2_MASK) + ret_mask = 0; +#if defined(RAMBLOCK_RET2_BIT_ICACHE) + ret_mask |= BIT(RAMBLOCK_RET2_BIT_ICACHE); +#endif +#if defined(RAMBLOCK_RET2_BIT_DCACHE) + ret_mask |= BIT(RAMBLOCK_RET2_BIT_DCACHE); +#endif + nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 0, ret_mask, enable); + nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 1, ret_mask, enable); +#endif /* defined(RAMBLOCK_RET2_MASK) */ +} + static void power_domain_init(void) { /* @@ -75,28 +99,12 @@ static void power_domain_init(void) soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0); nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false); - - nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET_BIT_ICACHE, false); - nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET_BIT_DCACHE, false); - nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET_BIT_ICACHE, false); - nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET_BIT_DCACHE, false); -#if defined(RAMBLOCK_RET2_BIT_ICACHE) - nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET2_BIT_ICACHE, false); - nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET2_BIT_ICACHE, false); -#endif -#if defined(RAMBLOCK_RET2_BIT_DCACHE) - nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET2_BIT_DCACHE, false); - nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET2_BIT_DCACHE, false); -#endif + nrf_soc_memconf_retain_set(false); nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET_MASK, true); nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET_MASK, true); #if defined(RAMBLOCK_RET2_MASK) - /* - * TODO: Use nrf_memconf_ramblock_ret2_mask_enable_set() function - * when will be provided by HAL. - */ - NRF_MEMCONF->POWER[0].RET2 = RAMBLOCK_RET2_MASK; - NRF_MEMCONF->POWER[1].RET2 = RAMBLOCK_RET2_MASK; + nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET2_MASK, true); + nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET2_MASK, true); #endif } @@ -173,26 +181,23 @@ void soc_early_init_hook(void) DT_PROP_OR(DT_NODELABEL(nfct), nfct_pins_as_gpios, 0)) { nrf_nfct_pad_config_enable_set(NRF_NFCT, false); } + + /* This is a workaround for not yet having upstream patches for properly handling + * pin retention. It should be removed as part of the next upmerge. + */ + if (IS_ENABLED(CONFIG_SOC_NRF54H20_DISABLE_ALL_GPIO_RETENTION_WORKAROUND)) { + NRF_GPIO_Type *gpio_regs[GPIO_COUNT] = GPIO_REG_LIST; + + for (int i = 0; i < NRFX_ARRAY_SIZE(gpio_regs); i++) { + nrf_gpio_port_retain_set(gpio_regs[i], 0); + } + } } #if defined(CONFIG_SOC_LATE_INIT_HOOK) void soc_late_init_hook(void) { -#if defined(CONFIG_SOC_NRF54H20_TDD_ENABLE) - int err_tdd; - - err_tdd = ironside_se_tdd_configure(IRONSIDE_SE_TDD_CONFIG_ON_DEFAULT); - __ASSERT(err_tdd == 0, "err_tdd was %d", err_tdd); - - UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 3, GPIO_PIN_CNF_CTRLSEL_TND); - UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 4, GPIO_PIN_CNF_CTRLSEL_TND); - UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 5, GPIO_PIN_CNF_CTRLSEL_TND); - UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 6, GPIO_PIN_CNF_CTRLSEL_TND); - UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 7, GPIO_PIN_CNF_CTRLSEL_TND); - -#endif - #if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) int err_cpuconf; @@ -205,22 +210,16 @@ void soc_late_init_hook(void) void *radiocore_address = NULL; #if DT_NODE_EXISTS(DT_NODELABEL(cpurad_slot1_partition)) - if (PARTITION_IS_RUNNING_APP_PARTITION(slot1_partition)) { - radiocore_address = - (void *)(DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(cpurad_slot1_partition))) + - DT_REG_ADDR(DT_NODELABEL(cpurad_slot1_partition)) + - CONFIG_ROM_START_OFFSET); + if (PARTITION_IS_RUNNING_APP_PARTITION(cpuapp_slot1_partition)) { + radiocore_address = (void *)(FIXED_PARTITION_ADDRESS(cpurad_slot1_partition) + + CONFIG_ROM_START_OFFSET); } else { - radiocore_address = - (void *)(DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(cpurad_slot0_partition))) + - DT_REG_ADDR(DT_NODELABEL(cpurad_slot0_partition)) + - CONFIG_ROM_START_OFFSET); + radiocore_address = (void *)(FIXED_PARTITION_ADDRESS(cpurad_slot0_partition) + + CONFIG_ROM_START_OFFSET); } #else radiocore_address = - (void *)(DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(cpurad_slot0_partition))) + - DT_REG_ADDR(DT_NODELABEL(cpurad_slot0_partition)) + - CONFIG_ROM_START_OFFSET); + (void *)(FIXED_PARTITION_ADDRESS(cpurad_slot0_partition) + CONFIG_ROM_START_OFFSET); #endif if (IS_ENABLED(CONFIG_SOC_NRF54H20_CPURAD_ENABLE_CHECK_VTOR) && diff --git a/soc/nordic/nrf54h/soc.h b/soc/nordic/nrf54h/soc.h index 566c07a8c2cb..69c22e52bd16 100644 --- a/soc/nordic/nrf54h/soc.h +++ b/soc/nordic/nrf54h/soc.h @@ -36,4 +36,11 @@ #define RAMBLOCK_RET2_BIT_DCACHE MEMCONF_POWER_RET2_MEM7_Pos #endif +/** + * @brief Enable or disable the retention for cache RAM blocks. + * + * @param enable True if the retention is to be enabled, false otherwise. + */ +void nrf_soc_memconf_retain_set(bool enable); + #endif /* SOC_ARM_NORDIC_NRF_NRF54H_SOC_H_ */ diff --git a/soc/nordic/nrf54l/CMakeLists.txt b/soc/nordic/nrf54l/CMakeLists.txt index cebbda571b68..b220b9d2a7a2 100644 --- a/soc/nordic/nrf54l/CMakeLists.txt +++ b/soc/nordic/nrf54l/CMakeLists.txt @@ -6,3 +6,16 @@ zephyr_library_sources( ../validate_rram_partitions.c ) zephyr_include_directories(.) + +dt_nodelabel(kmu_push_area_node NODELABEL nrf_kmu_reserved_push_area) + +# We need a buffer in memory in a static location which can be used by +# the KMU peripheral. The KMU has a static destination address, we chose +# this address to be 0x20000000, which is the first address in the SRAM. +if(NOT CONFIG_BUILD_WITH_TFM AND CONFIG_PSA_NEED_CRACEN_KMU_DRIVER AND NOT kmu_push_area_node) +# Exclamation mark is printable character with the lowest number in ASCII table. +# We are sure that this file will be included first. +zephyr_linker_sources(RAM_SECTIONS SORT_KEY ! kmu_push_area_section.ld) + +zephyr_linker_section(NAME ".nrf_kmu_reserved_push_area" ADDRESS "${RAM_ADDR}" GROUP RAM_REGION NOINIT) +endif() diff --git a/soc/nordic/nrf54l/Kconfig b/soc/nordic/nrf54l/Kconfig index 114c1dc6b5a6..7c09a90cf83c 100644 --- a/soc/nordic/nrf54l/Kconfig +++ b/soc/nordic/nrf54l/Kconfig @@ -8,37 +8,53 @@ config SOC_SERIES_NRF54LX select HAS_NRFX select HAS_NORDIC_DRIVERS select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE + select NRF_PLATFORM_LUMOS config SOC_NRF54L_CPUAPP_COMMON bool select ARM - select ARMV8_M_DSP select CPU_CORTEX_M33 select CPU_CORTEX_M_HAS_DWT - select CPU_HAS_ARM_MPU select CPU_HAS_ICACHE - select CPU_HAS_ARM_SAU - select CPU_HAS_FPU select HAS_HW_NRF_RADIO_IEEE802154 select HAS_POWEROFF select HAS_NORDIC_RAM_CTRL - select HAS_SWO config SOC_NRF54L05_CPUAPP select SOC_NRF54L_CPUAPP_COMMON + select ARMV8_M_DSP + select CPU_HAS_ARM_MPU + select CPU_HAS_ARM_SAU + select CPU_HAS_FPU + select HAS_SWO config SOC_NRF54L10_CPUAPP select SOC_NRF54L_CPUAPP_COMMON + select ARMV8_M_DSP + select CPU_HAS_ARM_MPU + select CPU_HAS_ARM_SAU + select CPU_HAS_FPU + select HAS_SWO config SOC_NRF54L15_CPUAPP select SOC_NRF54L_CPUAPP_COMMON select SOC_COMPATIBLE_NRF54L15 select SOC_COMPATIBLE_NRF54L15_CPUAPP + select ARMV8_M_DSP + select CPU_HAS_ARM_MPU + select CPU_HAS_ARM_SAU + select CPU_HAS_FPU + select HAS_SWO config SOC_NRF54LM20A_ENGA_CPUAPP select SOC_NRF54L_CPUAPP_COMMON select SOC_COMPATIBLE_NRF54LM20A select SOC_COMPATIBLE_NRF54LM20A_CPUAPP + select ARMV8_M_DSP + select CPU_HAS_ARM_MPU + select CPU_HAS_ARM_SAU + select CPU_HAS_FPU + select HAS_SWO config SOC_NRF54L05_CPUFLPR select RISCV_CORE_NORDIC_VPR @@ -55,12 +71,6 @@ config SOC_NRF54LM20A_ENGA_CPUFLPR if SOC_SERIES_NRF54LX -config SOC_NRF54LX_SKIP_CLOCK_CONFIG - bool "Skip clock frequency configuration in system initialization" - help - With this option, the CPU clock frequency is not set during system initialization. - The CPU runs with the default, hardware-selected frequency. - config SOC_NRF54LX_DISABLE_FICR_TRIMCNF bool "Disable trimming of the device" default y if TRUSTED_EXECUTION_NONSECURE diff --git a/soc/nordic/nrf54l/Kconfig.defconfig b/soc/nordic/nrf54l/Kconfig.defconfig index 9e84d3bc09f7..3274abc88b8a 100644 --- a/soc/nordic/nrf54l/Kconfig.defconfig +++ b/soc/nordic/nrf54l/Kconfig.defconfig @@ -32,6 +32,10 @@ choice NULL_POINTER_EXCEPTION_DETECTION default NULL_POINTER_EXCEPTION_DETECTION_NONE endchoice +config ROM_START_OFFSET + default 0 if PARTITION_MANAGER_ENABLED + default 0x800 if BOOTLOADER_MCUBOOT + endif # ARM if RISCV diff --git a/soc/nordic/nrf54l/kmu_push_area_section.ld b/soc/nordic/nrf54l/kmu_push_area_section.ld new file mode 100644 index 000000000000..e8c8cd9f09ad --- /dev/null +++ b/soc/nordic/nrf54l/kmu_push_area_section.ld @@ -0,0 +1,19 @@ +# This section must be loaded first of all the +# custom sections because we want it to be placed +# at the top address of RAM. +SECTION_PROLOGUE(NRF_KMU_RESERVED_PUSH_SECTION,(NOLOAD) ,) +{ + __nrf_kmu_reserved_push_area = .; + *(.nrf_kmu_reserved_push_area) + __nrf_kmu_reserved_push_area_end = .; +} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) + +# It doesn't seem to be possible to enforce placing a section +# at a specific address in memory using the Zephyr SECTION macros. +# So this assert is necessary to avoid accidentatly moving this +# section to a different address. +ASSERT(__nrf_kmu_reserved_push_area == RAM_ADDR, "Error: \ + The section NRF_KMU_RESERVED_PUSH_SECTION needs to be \ + placed on the top RAM address but it is not, please edit \ + your linker scripts to make sure that it is placed on \ + the to RAM address.") diff --git a/soc/nordic/nrf91/Kconfig b/soc/nordic/nrf91/Kconfig index ed38eff73a2d..9f55cdd77ed9 100644 --- a/soc/nordic/nrf91/Kconfig +++ b/soc/nordic/nrf91/Kconfig @@ -24,6 +24,16 @@ config NRF_SPU_FLASH_REGION_SIZE help FLASH region size for the NRF_SPU peripheral +config NRF_TRUSTZONE_FLASH_REGION_SIZE + hex + default NRF_SPU_FLASH_REGION_SIZE + help + Define the flash region size from a TrustZone perspective. + This is used when we set the security attributes(S/NSC/NS) of a region + in TrustZone enabled devices. + In practice this option defines the granularity of the security attributes, + i.e. the smallest region that can be set to secure or non-secure. + config NRF_SPU_RAM_REGION_SIZE hex default 0x2000 @@ -34,4 +44,14 @@ config NRF_ENABLE_ICACHE bool "Instruction cache (I-Cache)" default y +config NRF_TRUSTZONE_RAM_REGION_SIZE + hex + default NRF_SPU_RAM_REGION_SIZE + help + Define the RAM region size from a TrustZone perspective. + This is used when we set the security attributes(S/NSC/NS) of a region + in TrustZone enabled devices. + In practice this option defines the granularity of the security attributes, + i.e. the smallest region that can be set to secure or non-secure. + endif # SOC_SERIES_NRF91X diff --git a/soc/nordic/validate_base_addresses.c b/soc/nordic/validate_base_addresses.c index 4f17e32e5d5b..f8e5245b51cb 100644 --- a/soc/nordic/validate_base_addresses.c +++ b/soc/nordic/validate_base_addresses.c @@ -346,7 +346,7 @@ CHECK_DT_REG(uart134, NRF_UARTE134); CHECK_DT_REG(uart135, NRF_UARTE135); CHECK_DT_REG(uart136, NRF_UARTE136); CHECK_DT_REG(uart137, NRF_UARTE137); -#if !defined(CONFIG_SOC_SERIES_NRF54HX) +#if !defined(CONFIG_SOC_SERIES_NRF54HX) && !defined(CONFIG_SOC_SERIES_NRF92X) CHECK_DT_REG(uicr, NRF_UICR); #else CHECK_DT_REG(uicr, NRF_APPLICATION_UICR); diff --git a/submanifests/optional.yaml b/submanifests/optional.yaml index 04bdd669a921..57ad7affdd1c 100644 --- a/submanifests/optional.yaml +++ b/submanifests/optional.yaml @@ -35,7 +35,7 @@ manifest: groups: - optional - name: tf-m-tests - revision: a286347e6a5dd37a9a5e960450ffc0260d63fb27 + revision: a90702bcb8fadb6f70daf0ffbb13888dfe63fc99 path: modules/tee/tf-m/tf-m-tests remote: upstream groups: diff --git a/subsys/bluetooth/audio/bap_scan_delegator.c b/subsys/bluetooth/audio/bap_scan_delegator.c index da07fab411c8..8c21b806900f 100644 --- a/subsys/bluetooth/audio/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/bap_scan_delegator.c @@ -149,7 +149,7 @@ static bool bis_syncs_unique_or_no_pref(uint32_t requested_bis_syncs, return true; } - return (requested_bis_syncs & aggregated_bis_syncs) != 0U; + return (requested_bis_syncs & aggregated_bis_syncs) == 0U; } static bool valid_bis_sync_request(uint32_t requested_bis_syncs, uint32_t aggregated_bis_syncs) @@ -938,8 +938,7 @@ static int scan_delegator_mod_src(struct bt_conn *conn, bis_sync_change_requested = true; } - if (!valid_bis_sync_request(internal_state->requested_bis_sync[i], - aggregated_bis_syncs)) { + if (!valid_bis_sync_request(requested_bis_sync[i], aggregated_bis_syncs)) { LOG_DBG("Invalid BIS Sync request[%d]", i); ret = BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED); goto unlock_return; diff --git a/subsys/bluetooth/audio/csip_set_member.c b/subsys/bluetooth/audio/csip_set_member.c index cfeb6ac6e45f..5656728f4e5d 100644 --- a/subsys/bluetooth/audio/csip_set_member.c +++ b/subsys/bluetooth/audio/csip_set_member.c @@ -520,8 +520,10 @@ static void csip_security_changed(struct bt_conn *conn, bt_security_t level, return; } - /* Check if client is set with FLAG_NOTIFY_LOCK */ - if (atomic_test_bit(client->flags, FLAG_NOTIFY_LOCK)) { + /* Check if client has pending notifications */ + if (atomic_test_bit(client->flags, FLAG_NOTIFY_LOCK) || + atomic_test_bit(client->flags, FLAG_NOTIFY_SIRK) || + atomic_test_bit(client->flags, FLAG_NOTIFY_SIZE)) { notify_work_reschedule(K_NO_WAIT); break; } diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index f4fb9ab9bc75..9ba9cb325855 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -102,27 +102,6 @@ config BT_BUF_ACL_RX_COUNT_EXTRA connection and uses one Rx buffer across all connections to receive a fragment from the Controller. -config BT_BUF_ACL_RX_COUNT - int "[DEPRECATED] Number of incoming ACL data buffers" - default 0 - range 0 256 - help - Number or incoming ACL data buffers sent from the Controller to the - Host. - In a combined Host and Controller build the buffers are shared and - therefore Controller to Host flow control is not needed. - - In a Host only build with Controller to Host flow control enabled - the Host will inform the Controller about the maximum number of - buffers by setting this value in the Host Buffer Size command. - - When Controller to Host flow control is not enabled the Controller - can assume that the Host has infinite amount of buffers. - - For both configurations, there is an additional requirement that is - enforced by a build-time check: BT_BUF_ACL_RX_COUNT needs to be at - least one greater than BT_MAX_CONN. - config BT_BUF_EVT_RX_SIZE int "Maximum supported HCI Event buffer length" default $(UINT8_MAX) if (BT_EXT_ADV && BT_OBSERVER) || BT_PER_ADV_SYNC || BT_DF_CONNECTION_CTE_RX || BT_CLASSIC || BT_CHANNEL_SOUNDING || BT_LE_EXTENDED_FEAT_SET @@ -230,9 +209,12 @@ config BT_HCI_VS Host and/or Controller. This enables Set Version Information, Supported Commands, Supported Features vendor commands. +config BT_HCI_VS_FATAL_ERROR_SUPPORT + bool + config BT_HCI_VS_FATAL_ERROR bool "Allow vendor specific HCI event Zephyr Fatal Error" - depends on BT_HCI_VS + depends on BT_HCI_VS && BT_HCI_VS_FATAL_ERROR_SUPPORT help Enable emitting HCI Vendor-Specific events for system and Controller errors that are unrecoverable. diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 926fc060a89c..98107940b949 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -138,10 +138,12 @@ config HAS_BT_CTLR bool config BT_LL_SW_SPLIT - bool "Software-based Bluetooth LE Link Layer" + bool "Software-based Bluetooth LE Link Layer [EXPERIMENTAL]" default y depends on DT_HAS_ZEPHYR_BT_HCI_LL_SW_SPLIT_ENABLED select HAS_BT_CTLR + select EXPERIMENTAL + select ENTROPY_GENERATOR help Use Zephyr software Bluetooth LE Link Layer ULL LLL split implementation. @@ -1188,6 +1190,21 @@ rsource "Kconfig.df" rsource "Kconfig.ll_sw_split" rsource "Kconfig.dtm" +config BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE_SUPPORT + bool + +config BT_CTLR_ASSERT_DEBUG + bool "Development asserts" + default y + help + This option enables development asserts used for code coverage. + + The Controller will continue to function without memory leak or corruption with these + assertion checks disabled. Example, run-time mis-aligned memory access etc. which do + otherwise implicitly cause CPU fault during development testing. But these type of + asserted are essentially required for debugging, code and unit test coverage during + development cycle. + config BT_CTLR_ASSERT_HANDLER bool "Application Defined Assertion Handler" help @@ -1197,6 +1214,18 @@ config BT_CTLR_ASSERT_HANDLER and will be invoked whenever the controller code encounters an unrecoverable error. +config BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE + bool "Assertions optimized for code size" + depends on BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE_SUPPORT + default y + help + Optimize Controller assertion check for code size. + + Example, reduces assertion check code size for ARM Cortex-M CPUs by using the undefined + instruction exception. + `arm-none-eabi-addr2line` commandline can be used to get the source file and line number + from the program counter value. + config BT_CTLR_VS_SCAN_REQ_RX bool "Use scan request reporting" depends on BT_HCI_VS && !BT_CTLR_ADV_EXT diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 950e9bc7e58b..744727eb11f3 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -17,13 +17,13 @@ config BT_LLL_VENDOR_NORDIC select EXPERIMENTAL if !ENTROPY_HAS_DRIVER select BT_HAS_HCI_VS + select BT_HCI_VS_FATAL_ERROR_SUPPORT select BT_CTLR_CRYPTO_SUPPORT select BT_CTLR_LE_ENC_SUPPORT if BT_CTLR_CRYPTO_SUPPORT && \ !BT_CTLR_DATA_LENGTH_CLEAR && \ !BT_CTLR_PHY_2M_NRF select BT_CTLR_PRIVACY_SUPPORT if BT_CTLR_CRYPTO_SUPPORT && \ - !SOC_SERIES_NRF51X && \ - !SOC_COMPATIBLE_NRF54LX + !SOC_SERIES_NRF51X select BT_CTLR_CONN_PARAM_REQ_SUPPORT select BT_CTLR_EXT_REJ_IND_SUPPORT select BT_CTLR_PER_INIT_FEAT_XCHG_SUPPORT @@ -70,6 +70,8 @@ config BT_LLL_VENDOR_NORDIC select BT_TICKER_PREFER_START_BEFORE_STOP if BT_TICKER_SLOT_AGNOSTIC + select BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE_SUPPORT if CPU_CORTEX_M + default y help Use Nordic Lower Link Layer implementation. diff --git a/subsys/bluetooth/controller/hal/debug.h b/subsys/bluetooth/controller/hal/debug.h index 653aa304b070..98e827534fe7 100644 --- a/subsys/bluetooth/controller/hal/debug.h +++ b/subsys/bluetooth/controller/hal/debug.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Nordic Semiconductor ASA + * Copyright (c) 2016-2025 Nordic Semiconductor ASA * Copyright (c) 2016 Vinayak Kariappa Chettimada * * SPDX-License-Identifier: Apache-2.0 @@ -7,25 +7,79 @@ #include "common/assert.h" -#ifdef CONFIG_BT_CTLR_ASSERT_HANDLER +#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER) void bt_ctlr_assert_handle(char *file, uint32_t line); + +#if defined(CONFIG_BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE) +BUILD_ASSERT(IS_ENABLED(CONFIG_CPU_CORTEX_M)); +/* Generate assertion as undefined instruction exception. + */ +#define LL_ASSERT(x) \ + do { \ + if (unlikely(!(x))) { \ + __asm__ inline volatile (".inst 0xde00\n"); \ + } \ + } while (0) + +#else /* !CONFIG_BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE */ +/* Generate assertion with file name and line number. + * NOTE: Variable code size increase per assertion check, depends on full file name path string + * length. + */ #define LL_ASSERT(cond) \ - if (!(cond)) { \ + if (unlikely(!(cond))) { \ BT_ASSERT_PRINT(cond); \ bt_ctlr_assert_handle(__FILE__, __LINE__); \ } +#endif /* !CONFIG_BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE */ + #define LL_ASSERT_MSG(cond, fmt, ...) \ - if (!(cond)) { \ + if (unlikely(!(cond))) { \ BT_ASSERT_PRINT(cond); \ BT_ASSERT_PRINT_MSG(fmt, ##__VA_ARGS__); \ bt_ctlr_assert_handle(__FILE__, __LINE__); \ } -#else + +#else /* !CONFIG_BT_CTLR_ASSERT_HANDLER */ + +#if defined(CONFIG_BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE) +BUILD_ASSERT(IS_ENABLED(CONFIG_CPU_CORTEX_M)); +/* Generate assertion as undefined instruction exception. + */ +#define LL_ASSERT(x) \ + do { \ + if (unlikely(!(x))) { \ + __asm__ inline volatile (".inst 0xde00\n"); \ + } \ + } while (0) + +#else /* !CONFIG_BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE */ #define LL_ASSERT(cond) \ BT_ASSERT(cond) +#endif /* !CONFIG_BT_CTLR_ASSERT_OPTIMIZE_FOR_SIZE */ + #define LL_ASSERT_MSG(cond, fmt, ...) \ BT_ASSERT_MSG(cond, fmt, ##__VA_ARGS__) -#endif +#endif /* !CONFIG_BT_CTLR_ASSERT_HANDLER */ + +/* Fatal asserts. + * The Controller will otherwise misbehave causing memory leak or system-wide memory corruptions due + * to uncontrolled DMA transfers etc. + * It is not safe to disable these assertion checks. + */ +#define LL_ASSERT_ERR(cond) LL_ASSERT(cond) + +/* Development asserts. + * The Controller will continue to function without memory leak or corruption with these assertion + * checks disabled. Example, run-time mis-aligned memory access etc. which do otherwise implicitly + * cause CPU fault during development testing. But these type of asserted are essentially required + * for debugging, code and unit test coverage during development cycle. + */ +#if defined(CONFIG_BT_CTLR_ASSERT_DEBUG) +#define LL_ASSERT_DBG(cond) LL_ASSERT(cond) +#else /* !CONFIG_BT_CTLR_ASSERT_DEBUG */ +#define LL_ASSERT_DBG(cond) ARG_UNUSED((cond)) +#endif /* !CONFIG_BT_CTLR_ASSERT_DEBUG */ #if defined(CONFIG_BT_CTLR_ASSERT_VENDOR) #define LL_ASSERT_INFO1(cond, param) \ diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 683c4cadf919..81856d7c428d 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -3222,7 +3222,7 @@ static void le_df_connection_iq_report(struct node_rx_pdu *node_rx, struct net_b phy_rx = lll->phy_rx; /* Make sure the report is generated for connection on PHY UNCODED */ - LL_ASSERT(phy_rx != PHY_CODED); + LL_ASSERT_DBG(phy_rx != PHY_CODED); #else phy_rx = PHY_1M; #endif /* CONFIG_BT_CTLR_PHY */ @@ -4412,7 +4412,7 @@ static void le_cis_request(struct pdu_data *pdu_data, * event. */ node = pdu_data; - LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_conn_iso_estab)); + LL_ASSERT_DBG(IS_PTR_ALIGNED(node, struct node_rx_conn_iso_estab)); req = node; if (!(ll_feat_get() & BIT64(BT_LE_FEAT_BIT_ISO_CHANNELS)) || @@ -4459,7 +4459,7 @@ static void le_cis_established(struct pdu_data *pdu_data, * event. */ node = pdu_data; - LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_conn_iso_estab)); + LL_ASSERT_DBG(IS_PTR_ALIGNED(node, struct node_rx_conn_iso_estab)); est = node; sep->status = est->status; @@ -4518,7 +4518,7 @@ static void le_per_adv_sync_transfer_received(struct pdu_data *pdu_data_rx, * event. */ node = pdu_data_rx; - LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_past_received)); + LL_ASSERT_DBG(IS_PTR_ALIGNED(node, struct node_rx_past_received)); se = node; sep->status = se->rx_sync.status; @@ -5273,9 +5273,9 @@ NET_BUF_POOL_FIXED_DEFINE(vs_err_tx_pool, 1, BT_BUF_EVT_RX_SIZE, 0, NULL); * the alias is defined here. */ #if defined(CONFIG_CPU_CORTEX_M) -typedef struct bt_hci_vs_fata_error_cpu_data_cortex_m bt_hci_vs_fatal_error_cpu_data; +static struct net_buf *vs_err_evt_create(uint8_t subevt, uint8_t len); -static void vs_err_fatal_cpu_data_fill(bt_hci_vs_fatal_error_cpu_data *cpu_data, +static void vs_err_fatal_cpu_data_fill(struct bt_hci_vs_fatal_error_cpu_data_cortex_m *cpu_data, const struct arch_esf *esf) { cpu_data->a1 = sys_cpu_to_le32(esf->basic.a1); @@ -5284,9 +5284,38 @@ static void vs_err_fatal_cpu_data_fill(bt_hci_vs_fatal_error_cpu_data *cpu_data, cpu_data->a4 = sys_cpu_to_le32(esf->basic.a4); cpu_data->ip = sys_cpu_to_le32(esf->basic.ip); cpu_data->lr = sys_cpu_to_le32(esf->basic.lr); + cpu_data->pc = sys_cpu_to_le32(esf->basic.pc); cpu_data->xpsr = sys_cpu_to_le32(esf->basic.xpsr); } -#endif /* CONFIG_CPU_CORTEX_M */ + +struct net_buf *hci_vs_err_stack_frame(unsigned int reason, const struct arch_esf *esf) +{ + /* Prepare vendor specific HCI Fatal Error event */ + struct bt_hci_vs_fatal_error_stack_frame *sf; + struct bt_hci_vs_fatal_error_cpu_data_cortex_m *cpu_data; + struct net_buf *buf; + + buf = vs_err_evt_create(BT_HCI_EVT_VS_ERROR_DATA_TYPE_STACK_FRAME, + sizeof(*sf) + sizeof(*cpu_data)); + if (buf != NULL) { + sf = net_buf_add(buf, (sizeof(*sf) + sizeof(*cpu_data))); + sf->reason = sys_cpu_to_le32(reason); + sf->cpu_type = BT_HCI_EVT_VS_ERROR_CPU_TYPE_CORTEX_M; + + vs_err_fatal_cpu_data_fill((void *)sf->cpu_data, esf); + } else { + LOG_WRN("Can't create HCI Fatal Error event"); + } + + return buf; +} + +#else /* !CONFIG_CPU_CORTEX_M */ +struct net_buf *hci_vs_err_stack_frame(unsigned int reason, const struct arch_esf *esf) +{ + return NULL; +} +#endif /* !CONFIG_CPU_CORTEX_M */ static struct net_buf *vs_err_evt_create(uint8_t subevt, uint8_t len) { @@ -5310,29 +5339,6 @@ static struct net_buf *vs_err_evt_create(uint8_t subevt, uint8_t len) return buf; } -struct net_buf *hci_vs_err_stack_frame(unsigned int reason, const struct arch_esf *esf) -{ - /* Prepare vendor specific HCI Fatal Error event */ - struct bt_hci_vs_fatal_error_stack_frame *sf; - bt_hci_vs_fatal_error_cpu_data *cpu_data; - struct net_buf *buf; - - buf = vs_err_evt_create(BT_HCI_EVT_VS_ERROR_DATA_TYPE_STACK_FRAME, - sizeof(*sf) + sizeof(*cpu_data)); - if (buf != NULL) { - sf = net_buf_add(buf, (sizeof(*sf) + sizeof(*cpu_data))); - sf->reason = sys_cpu_to_le32(reason); - sf->cpu_type = BT_HCI_EVT_VS_ERROR_CPU_TYPE_CORTEX_M; - - vs_err_fatal_cpu_data_fill( - (bt_hci_vs_fatal_error_cpu_data *)sf->cpu_data, esf); - } else { - LOG_ERR("Can't create HCI Fatal Error event"); - } - - return buf; -} - static struct net_buf *hci_vs_err_trace_create(uint8_t data_type, const char *file_path, uint32_t line, uint64_t pc) @@ -5520,7 +5526,7 @@ static void vs_le_df_connection_iq_report(struct node_rx_pdu *node_rx, struct ne phy_rx = lll->phy_rx; /* Make sure the report is generated for connection on PHY UNCODED */ - LL_ASSERT(phy_rx != PHY_CODED); + LL_ASSERT_DBG(phy_rx != PHY_CODED); #else phy_rx = PHY_1M; #endif /* CONFIG_BT_CTLR_PHY */ @@ -6300,7 +6306,7 @@ int hci_iso_handle(struct net_buf *buf, struct net_buf **evt) /* Start Fragmentation */ /* FIXME: need to ensure ISO-AL returns proper isoal_status. - * Currently there are cases where ISO-AL calls LL_ASSERT. + * Currently there are cases where ISO-AL calls LL_ASSERT_ERR. */ isoal_status_t isoal_status = isoal_tx_sdu_fragment(stream->dp->source_hdl, &sdu_frag_tx); @@ -6554,7 +6560,7 @@ static inline void le_dir_adv_report(struct pdu_adv *adv, struct net_buf *buf, return; } - LL_ASSERT(adv->type == PDU_ADV_TYPE_DIRECT_IND); + LL_ASSERT_DBG(adv->type == PDU_ADV_TYPE_DIRECT_IND); #if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 if (dup_scan && @@ -6624,7 +6630,7 @@ static inline void le_mesh_scan_report(struct pdu_adv *adv, uint32_t instant; uint8_t chan; - LL_ASSERT(adv->type == PDU_ADV_TYPE_NONCONN_IND); + LL_ASSERT_DBG(adv->type == PDU_ADV_TYPE_NONCONN_IND); /* Filter based on currently active Scan Filter */ if (sf_curr < ARRAY_SIZE(scan_filters) && @@ -7093,7 +7099,7 @@ static void ext_adv_pdu_frag(uint8_t evt_type, uint8_t phy, uint8_t sec_phy, *data_len_total -= data_len_frag; *evt_buf = bt_buf_get_rx(BT_BUF_EVT, BUF_GET_TIMEOUT); - LL_ASSERT(*evt_buf); + LL_ASSERT_ERR(*evt_buf); net_buf_frag_add(buf, *evt_buf); @@ -7630,7 +7636,7 @@ static void le_ext_adv_report(struct pdu_data *pdu_data, * event. */ evt_buf = bt_buf_get_rx(BT_BUF_EVT, BUF_GET_TIMEOUT); - LL_ASSERT(evt_buf); + LL_ASSERT_ERR(evt_buf); net_buf_frag_add(buf, evt_buf); @@ -7726,7 +7732,7 @@ static void le_per_adv_sync_established(struct pdu_data *pdu_data, * event. */ node = pdu_data; - LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_sync)); + LL_ASSERT_DBG(IS_PTR_ALIGNED(node, struct node_rx_sync)); se = node; sep->status = se->status; @@ -8006,7 +8012,7 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data, data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL; evt_buf = bt_buf_get_rx(BT_BUF_EVT, BUF_GET_TIMEOUT); - LL_ASSERT(evt_buf); + LL_ASSERT_ERR(evt_buf); net_buf_frag_add(buf, evt_buf); @@ -8062,7 +8068,7 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data, */ if (!evt_buf) { evt_buf = bt_buf_get_rx(BT_BUF_EVT, BUF_GET_TIMEOUT); - LL_ASSERT(evt_buf); + LL_ASSERT_ERR(evt_buf); net_buf_frag_add(buf, evt_buf); } @@ -8147,7 +8153,7 @@ static void le_big_sync_established(struct pdu_data *pdu, * established event. */ node = pdu; - LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_sync_iso)); + LL_ASSERT_DBG(IS_PTR_ALIGNED(node, struct node_rx_sync_iso)); se = node; sep->status = se->status; @@ -8451,7 +8457,7 @@ static void le_conn_complete(struct pdu_data *pdu_data, uint16_t handle, * complete event. */ node = pdu_data; - LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cc)); + LL_ASSERT_DBG(IS_PTR_ALIGNED(node, struct node_rx_cc)); cc = node; status = cc->status; @@ -8588,7 +8594,7 @@ static void le_conn_update_complete(struct pdu_data *pdu_data, uint16_t handle, * update complete event. */ node = pdu_data; - LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cu)); + LL_ASSERT_DBG(IS_PTR_ALIGNED(node, struct node_rx_cu)); cu = node; sep->status = cu->status; @@ -8845,7 +8851,7 @@ static void encode_control(struct node_rx_pdu *node_rx, #elif defined(CONFIG_BT_CTLR_VS_SCAN_REQ_RX) le_vs_scan_req_received(pdu_data, node_rx, buf); #else - LL_ASSERT(0); + LL_ASSERT_DBG(0); #endif /* CONFIG_BT_CTLR_ADV_EXT */ break; #endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */ @@ -8984,7 +8990,7 @@ static void encode_control(struct node_rx_pdu *node_rx, #endif /* CONFIG_BT_CTLR_USER_EVT_RANGE > 0 */ default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); return; } } @@ -9212,7 +9218,7 @@ static void encode_data_ctrl(struct node_rx_pdu *node_rx, break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); return; } } @@ -9243,20 +9249,20 @@ void hci_acl_encode(struct node_rx_pdu *node_rx, struct net_buf *buf) memcpy(data, pdu_data->lldata, pdu_data->len); #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) if (hci_hbuf_total > 0) { - LL_ASSERT((hci_hbuf_sent - hci_hbuf_acked) < + LL_ASSERT_DBG((hci_hbuf_sent - hci_hbuf_acked) < hci_hbuf_total); hci_hbuf_sent++; /* Note: This requires linear handle values starting * from 0 */ - LL_ASSERT(handle < ARRAY_SIZE(hci_hbuf_pend)); + LL_ASSERT_DBG(handle < ARRAY_SIZE(hci_hbuf_pend)); hci_hbuf_pend[handle]++; } #endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index 8f3fd04d8e9e..43b2ad1ef656 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -91,21 +91,20 @@ isoal_status_t sink_sdu_alloc_hci(const struct isoal_sink *sink_ctx, const struct isoal_pdu_rx *valid_pdu, struct isoal_sdu_buffer *sdu_buffer) { + struct net_buf *buf; + ARG_UNUSED(sink_ctx); ARG_UNUSED(valid_pdu); /* TODO copy valid pdu into netbuf ? */ - struct net_buf *buf = bt_buf_get_rx(BT_BUF_ISO_IN, K_FOREVER); + buf = bt_buf_get_rx(BT_BUF_ISO_IN, K_FOREVER); + LL_ASSERT_ERR(buf); - if (buf) { - /* Increase reserved space for headers */ - net_buf_reset(buf); - net_buf_reserve(buf, BT_BUF_RESERVE + SDU_HCI_HDR_SIZE); - - sdu_buffer->dbuf = buf; - sdu_buffer->size = net_buf_tailroom(buf); - } else { - LL_ASSERT(0); - } + /* Increase reserved space for headers */ + net_buf_reset(buf); + net_buf_reserve(buf, BT_BUF_RESERVE + SDU_HCI_HDR_SIZE); + + sdu_buffer->dbuf = buf; + sdu_buffer->size = net_buf_tailroom(buf); return ISOAL_STATUS_OK; } @@ -212,11 +211,13 @@ isoal_status_t sink_sdu_write_hci(void *dbuf, const uint8_t *pdu_payload, const size_t consume_len) { + struct net_buf *buf; + ARG_UNUSED(sdu_written); - struct net_buf *buf = (struct net_buf *) dbuf; + buf = (struct net_buf *) dbuf; + LL_ASSERT_ERR(buf); - LL_ASSERT(buf); net_buf_add_mem(buf, pdu_payload, consume_len); return ISOAL_STATUS_OK; @@ -364,7 +365,7 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) LOG_DBG("Num Complete: 0x%04x:%u", handle, num_cmplt); err = bt_recv_prio(dev, buf); - LL_ASSERT(err == 0); + LL_ASSERT_DBG(err == 0); k_yield(); #endif /* CONFIG_BT_CONN || CONFIG_BT_CTLR_ADV_ISO */ @@ -392,7 +393,7 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) } err = bt_recv_prio(dev, buf); - LL_ASSERT(err == 0); + LL_ASSERT_DBG(err == 0); /* bt_recv_prio would not release normal evt * buf. @@ -470,7 +471,7 @@ static void node_rx_recv(const struct device *dev) #if defined(CONFIG_BT_CONN) || defined(CONFIG_BT_CTLR_ADV_ISO) struct net_buf *buf; - LL_ASSERT(node_rx == NULL); + LL_ASSERT_DBG(node_rx == NULL); buf = bt_buf_get_evt(BT_HCI_EVT_NUM_COMPLETED_PACKETS, false, K_FOREVER); @@ -482,7 +483,7 @@ static void node_rx_recv(const struct device *dev) k_yield(); #else /* !CONFIG_BT_CONN && !CONFIG_BT_CTLR_ADV_ISO */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); #endif /* !CONFIG_BT_CONN && !CONFIG_BT_CTLR_ADV_ISO */ num_cmplt = ll_rx_get((void *)&node_rx, &handle); @@ -589,7 +590,7 @@ static inline struct net_buf *encode_node(struct node_rx_pdu *node_rx, isoal_rx_pdu_recombine(dp->sink_hdl, &pckt_meta); /* TODO handle err */ - LL_ASSERT(err == ISOAL_STATUS_OK); + LL_ASSERT_ERR(err == ISOAL_STATUS_OK); } } #endif /* CONFIG_BT_CTLR_CONN_ISO */ @@ -613,13 +614,13 @@ static inline struct net_buf *encode_node(struct node_rx_pdu *node_rx, isoal_rx.pdu = (void *)node_rx->pdu; err = isoal_rx_pdu_recombine(stream->dp->sink_hdl, &isoal_rx); - LL_ASSERT(err == ISOAL_STATUS_OK || - err == ISOAL_STATUS_ERR_SDU_ALLOC); + LL_ASSERT_ERR(err == ISOAL_STATUS_OK || + err == ISOAL_STATUS_ERR_SDU_ALLOC); } #endif /* CONFIG_BT_CTLR_SYNC_ISO */ } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } node_rx->hdr.next = NULL; @@ -630,7 +631,7 @@ static inline struct net_buf *encode_node(struct node_rx_pdu *node_rx, #endif /* CONFIG_BT_CTLR_SYNC_ISO || CONFIG_BT_CTLR_CONN_ISO */ default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -668,7 +669,7 @@ static inline struct net_buf *process_node(struct node_rx_pdu *node_rx) } break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } @@ -741,7 +742,7 @@ static inline struct net_buf *process_hbuf(struct node_rx_pdu *n) case HCI_CLASS_EVT_DISCARDABLE: case HCI_CLASS_EVT_REQUIRED: default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -823,7 +824,7 @@ static void recv_thread(void *p1, void *p2, void *p3) int err; err = k_poll(events, ARRAY_SIZE(events), K_FOREVER); - LL_ASSERT(err == 0 || err == -EINTR); + LL_ASSERT_ERR(err == 0 || err == -EINTR); if (false) { @@ -835,7 +836,7 @@ static void recv_thread(void *p1, void *p2, void *p3) #if !defined(CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE) } else if (events[EVENT_SEM].state == K_POLL_STATE_SEM_AVAILABLE) { err = k_sem_take(events[EVENT_SEM].sem, K_NO_WAIT); - LL_ASSERT(err == 0); + LL_ASSERT_DBG(err == 0); node_rx_recv(dev); #endif /* !CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE */ @@ -1047,7 +1048,7 @@ static int hci_driver_close(const struct device *dev) /* Resetting the LL stops all roles */ err = ll_deinit(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #if defined(CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE) /* Abort prio RX thread */ diff --git a/subsys/bluetooth/controller/include/ll.h b/subsys/bluetooth/controller/include/ll.h index 378686064e15..f807842e6c34 100644 --- a/subsys/bluetooth/controller/include/ll.h +++ b/subsys/bluetooth/controller/include/ll.h @@ -1,63 +1,39 @@ /* - * Copyright (c) 2016-2021 Nordic Semiconductor ASA + * Copyright (c) 2016-2025 Nordic Semiconductor ASA * Copyright (c) 2016 Vinayak Kariappa Chettimada * * SPDX-License-Identifier: Apache-2.0 */ +#if defined(CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING) +#define LL_ADV_HANDLE_MAPPING +#else /* !CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING */ +#define LL_ADV_HANDLE_MAPPING static __attribute__((always_inline)) inline +#endif /* !CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING */ + +/* Initialization and Reset Interfaces */ int ll_init(struct k_sem *sem_rx); int ll_deinit(void); void ll_reset(void); +/* Features Interfaces */ uint8_t ll_set_host_feature(uint8_t bit_number, uint8_t bit_value); uint64_t ll_feat_get(void); +/* Device Address Interfaces */ uint8_t ll_addr_set(uint8_t addr_type, uint8_t const *const p_bdaddr); uint8_t *ll_addr_get(uint8_t addr_type); uint8_t *ll_addr_read(uint8_t addr_type, uint8_t *const bdaddr); -#if defined(CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING) -uint8_t ll_adv_set_by_hci_handle_get(uint8_t hci_handle, uint8_t *handle); -uint8_t ll_adv_set_by_hci_handle_get_or_new(uint8_t hci_handle, - uint8_t *handle); -uint8_t ll_adv_set_hci_handle_get(uint8_t handle); -uint8_t ll_adv_iso_by_hci_handle_get(uint8_t hci_handle, uint8_t *handle); -uint8_t ll_adv_iso_by_hci_handle_new(uint8_t hci_handle, uint8_t *handle); -#else -static inline uint8_t ll_adv_set_by_hci_handle_get(uint8_t hci_handle, - uint8_t *handle) -{ - *handle = hci_handle; - return 0; -} - -static inline uint8_t ll_adv_set_by_hci_handle_get_or_new(uint8_t hci_handle, - uint8_t *handle) -{ - *handle = hci_handle; - return 0; -} - -static inline uint8_t ll_adv_set_hci_handle_get(uint8_t handle) -{ - return handle; -} - -static inline uint8_t ll_adv_iso_by_hci_handle_get(uint8_t hci_handle, - uint8_t *handle) -{ - *handle = hci_handle; - return 0; -} - -static inline uint8_t ll_adv_iso_by_hci_handle_new(uint8_t hci_handle, - uint8_t *handle) -{ - *handle = hci_handle; - return 0; -} -#endif +/* Advertising Handles Interfaces */ +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_set_by_hci_handle_get(uint8_t hci_handle, uint8_t *handle); +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_set_by_hci_handle_get_or_new(uint8_t hci_handle, + uint8_t *handle); +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_set_hci_handle_get(uint8_t handle); +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_iso_by_hci_handle_get(uint8_t hci_handle, uint8_t *handle); +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_iso_by_hci_handle_new(uint8_t hci_handle, uint8_t *handle); +/* Advertising State Interfaces */ #if defined(CONFIG_BT_CTLR_ADV_EXT) uint8_t ll_adv_params_set(uint8_t handle, uint16_t evt_prop, uint32_t interval, uint8_t adv_type, uint8_t own_addr_type, @@ -78,6 +54,7 @@ uint8_t ll_adv_data_set(uint8_t len, uint8_t const *const p_data); uint8_t ll_adv_scan_rsp_set(uint8_t len, uint8_t const *const p_data); #endif /* !CONFIG_BT_CTLR_ADV_EXT */ +/* Extended Advertising State Interfaces */ uint8_t ll_adv_aux_random_addr_set(uint8_t handle, uint8_t const *const addr); uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, uint8_t len, uint8_t const *const data); @@ -87,12 +64,15 @@ uint16_t ll_adv_aux_max_data_length_get(void); uint8_t ll_adv_aux_set_count_get(void); uint8_t ll_adv_aux_set_remove(uint8_t handle); uint8_t ll_adv_aux_set_clear(void); + +/* Periodic Advertising State Interfaces */ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags); uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t len, uint8_t const *const data); uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable); +/* Advertising Enable and Disable Interfaces */ #if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT) #if defined(CONFIG_BT_HCI_MESH_EXT) uint8_t ll_adv_enable(uint8_t handle, uint8_t enable, @@ -108,6 +88,7 @@ uint8_t ll_adv_enable(uint8_t enable); uint8_t ll_adv_disable_all(void); +/* Broadcast ISO State Interfaces */ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, uint32_t sdu_interval, uint16_t max_sdu, uint16_t max_latency, uint8_t rtn, uint8_t phy, @@ -121,6 +102,7 @@ uint8_t ll_big_test_create(uint8_t big_handle, uint8_t adv_handle, uint8_t pto, uint8_t encryption, uint8_t *bcode); uint8_t ll_big_terminate(uint8_t big_handle, uint8_t reason); +/* Scanning State Interfaces */ uint8_t ll_scan_params_set(uint8_t type, uint16_t interval, uint16_t window, uint8_t own_addr_type, uint8_t filter_policy); #if defined(CONFIG_BT_CTLR_ADV_EXT) @@ -129,24 +111,30 @@ uint8_t ll_scan_enable(uint8_t enable, uint16_t duration, uint16_t period); uint8_t ll_scan_enable(uint8_t enable); #endif /* !CONFIG_BT_CTLR_ADV_EXT */ +/* Periodic Advertising Sync State Interfaces */ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, uint8_t *adv_addr, uint16_t skip, uint16_t sync_timeout, uint8_t sync_cte_type); uint8_t ll_sync_create_cancel(void **rx); uint8_t ll_sync_terminate(uint16_t handle); uint8_t ll_sync_recv_enable(uint16_t handle, uint8_t enable); + +/* Periodic Advertising Sync Transfer Interfaces */ uint8_t ll_sync_transfer(uint16_t conn_handle, uint16_t service_data, uint16_t sync_handle); uint8_t ll_adv_sync_set_info_transfer(uint16_t conn_handle, uint16_t service_data, uint8_t adv_handle); uint8_t ll_past_param(uint16_t conn_handle, uint8_t mode, uint16_t skip, uint16_t timeout, uint8_t cte_type); uint8_t ll_default_past_param(uint8_t mode, uint16_t skip, uint16_t timeout, uint8_t cte_type); + +/* Broadcast ISO Sync Receiver State Interfaces */ uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle, uint8_t encryption, uint8_t *bcode, uint8_t mse, uint16_t sync_timeout, uint8_t num_bis, uint8_t *bis); uint8_t ll_big_sync_terminate(uint8_t big_handle, void **rx); +/* Connected ISO State Interfaces */ uint8_t ll_cig_parameters_open(uint8_t cig_id, uint32_t c_interval, uint32_t p_interval, uint8_t sca, uint8_t packing, uint8_t framing, @@ -172,6 +160,15 @@ uint8_t ll_cis_parameters_test_set(uint8_t cis_id, uint8_t nse, uint16_t c_pdu, uint16_t p_pdu, uint8_t c_phy, uint8_t p_phy, uint8_t c_bn, uint8_t p_bn); +uint8_t ll_cig_remove(uint8_t cig_id); +uint8_t ll_cis_create_check(uint16_t cis_handle, uint16_t acl_handle); +void ll_cis_create(uint16_t cis_handle, uint16_t acl_handle); +uint8_t ll_cis_accept(uint16_t handle); +uint8_t ll_cis_reject(uint16_t handle, uint8_t reason); +uint8_t ll_conn_iso_accept_timeout_get(uint16_t *timeout); +uint8_t ll_conn_iso_accept_timeout_set(uint16_t timeout); + +/* ISO SDU data Interfaces */ /* Must be implemented by vendor if vendor-specific data path is supported */ uint8_t ll_configure_data_path(uint8_t data_path_dir, uint8_t data_path_id, @@ -200,24 +197,19 @@ uint8_t ll_iso_read_test_counters(uint16_t handle, uint32_t *received_cnt, uint32_t *missed_cnt, uint32_t *failed_cnt); -uint8_t ll_cig_remove(uint8_t cig_id); - -uint8_t ll_cis_create_check(uint16_t cis_handle, uint16_t acl_handle); -void ll_cis_create(uint16_t cis_handle, uint16_t acl_handle); - -uint8_t ll_cis_accept(uint16_t handle); -uint8_t ll_cis_reject(uint16_t handle, uint8_t reason); - +/* Filter Accept List Interfaces */ uint8_t ll_fal_size_get(void); uint8_t ll_fal_clear(void); uint8_t ll_fal_add(bt_addr_le_t *addr); uint8_t ll_fal_remove(bt_addr_le_t *addr); +/* Privacy Accept List Interfaces */ uint8_t ll_pal_size_get(void); uint8_t ll_pal_clear(void); uint8_t ll_pal_add(const bt_addr_le_t *const addr, const uint8_t sid); uint8_t ll_pal_remove(const bt_addr_le_t *const addr, const uint8_t sid); +/* Private Resolvable Address Resolution Interfaces */ void ll_rl_id_addr_get(uint8_t rl_idx, uint8_t *id_addr_type, uint8_t *id_addr); uint8_t ll_rl_size_get(void); uint8_t ll_rl_clear(void); @@ -231,6 +223,7 @@ uint8_t ll_rl_enable(uint8_t enable); void ll_rl_timeout_set(uint16_t timeout); uint8_t ll_priv_mode_set(bt_addr_le_t *id_addr, uint8_t mode); +/* Connection State Interfaces */ #if defined(CONFIG_BT_CTLR_ADV_EXT) uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, uint8_t filter_policy, uint8_t peer_addr_type, @@ -267,10 +260,10 @@ uint8_t ll_tx_pwr_lvl_set(uint8_t handle_type, uint16_t handle, uint8_t ll_apto_get(uint16_t handle, uint16_t *const apto); uint8_t ll_apto_set(uint16_t handle, uint16_t apto); -uint32_t ll_length_req_send(uint16_t handle, uint16_t tx_octets, uint16_t tx_time); +uint8_t ll_length_req_send(uint16_t handle, uint16_t tx_octets, uint16_t tx_time); void ll_length_default_get(uint16_t *const max_tx_octets, uint16_t *const max_tx_time); -uint32_t ll_length_default_set(uint16_t max_tx_octets, uint16_t max_tx_time); +uint8_t ll_length_default_set(uint16_t max_tx_octets, uint16_t max_tx_time); void ll_length_max_get(uint16_t *const max_tx_octets, uint16_t *const max_tx_time, uint16_t *const max_rx_octets, @@ -283,7 +276,7 @@ uint8_t ll_phy_req_send(uint16_t handle, uint8_t tx, uint8_t flags, uint8_t rx); uint8_t ll_set_min_used_chans(uint16_t handle, uint8_t const phys, uint8_t const min_used_chans); -/* Direction Finding */ +/* Direction Finding Interfaces */ /* Sets CTE transmission parameters for periodic advertising */ uint8_t ll_df_set_cl_cte_tx_params(uint8_t adv_handle, uint8_t cte_len, uint8_t cte_type, uint8_t cte_count, @@ -316,12 +309,21 @@ void ll_df_read_ant_inf(uint8_t *switch_sample_rates, uint8_t *max_switch_pattern_len, uint8_t *max_cte_len); -/* Downstream - Data */ +/* Path Loss Monitoring Interfaces */ +uint8_t ll_conn_set_path_loss_parameters(uint16_t handle, + uint8_t high_threshold, + uint8_t high_hysteresis, + uint8_t low_threshold, + uint8_t low_hysteresis, + uint16_t min_time_spent); +uint8_t ll_conn_set_path_loss_reporting(uint16_t handle, uint8_t enable); + +/* Downstream - ACL Data */ void *ll_tx_mem_acquire(void); void ll_tx_mem_release(void *node_tx); int ll_tx_mem_enqueue(uint16_t handle, void *node_tx); -/* Upstream - Num. Completes, Events and Data */ +/* Upstream - Num. Completes, Events, ACL and ISO Data */ uint8_t ll_rx_get(void **node_rx, uint16_t *handle); void ll_rx_dequeue(void); void ll_rx_mem_release(void **node_rx); @@ -333,9 +335,6 @@ void ll_iso_tx_mem_release(void *tx); int ll_iso_tx_mem_enqueue(uint16_t handle, void *tx, void *link); void ll_iso_link_tx_release(void *link); -uint8_t ll_conn_iso_accept_timeout_get(uint16_t *timeout); -uint8_t ll_conn_iso_accept_timeout_set(uint16_t timeout); - /* External co-operation */ void ll_timeslice_ticker_id_get(uint8_t * const instance_index, uint8_t * const ticker_id); @@ -344,11 +343,35 @@ void ll_coex_ticker_id_get(uint8_t * const instance_index, void ll_radio_state_abort(void); uint32_t ll_radio_state_is_idle(void); -uint8_t ll_conn_set_path_loss_parameters(uint16_t handle, - uint8_t high_threshold, - uint8_t high_hysteresis, - uint8_t low_threshold, - uint8_t low_hysteresis, - uint16_t min_time_spent); +/* Static inline functions */ +#if !defined(CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING) +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_set_by_hci_handle_get(uint8_t hci_handle, uint8_t *handle) +{ + *handle = hci_handle; + return 0U; +} -uint8_t ll_conn_set_path_loss_reporting(uint16_t handle, uint8_t enable); +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_set_by_hci_handle_get_or_new(uint8_t hci_handle, + uint8_t *handle) +{ + *handle = hci_handle; + return 0U; +} + +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_set_hci_handle_get(uint8_t handle) +{ + return handle; +} + +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_iso_by_hci_handle_get(uint8_t hci_handle, uint8_t *handle) +{ + *handle = hci_handle; + return 0U; +} + +LL_ADV_HANDLE_MAPPING uint8_t ll_adv_iso_by_hci_handle_new(uint8_t hci_handle, uint8_t *handle) +{ + *handle = hci_handle; + return 0U; +} +#endif /* !CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING */ diff --git a/subsys/bluetooth/controller/include/ll_feat.h b/subsys/bluetooth/controller/include/ll_feat.h index 946441720769..9e5cd3144b7a 100644 --- a/subsys/bluetooth/controller/include/ll_feat.h +++ b/subsys/bluetooth/controller/include/ll_feat.h @@ -63,11 +63,11 @@ #define LL_FEAT_BIT_EXT_SCAN 0 #endif /* !CONFIG_BT_CTLR_EXT_SCAN_FP */ -#if defined(CONFIG_BT_CTLR_PHY_2M) +#if defined(CONFIG_BT_CTLR_PHY) && defined(CONFIG_BT_CTLR_PHY_2M) #define LL_FEAT_BIT_PHY_2M BIT64(BT_LE_FEAT_BIT_PHY_2M) -#else /* !CONFIG_BT_CTLR_PHY_2M */ +#else /* !CONFIG_BT_CTLR_PHY || !CONFIG_BT_CTLR_PHY_2M */ #define LL_FEAT_BIT_PHY_2M 0 -#endif /* !CONFIG_BT_CTLR_PHY_2M */ +#endif /* !CONFIG_BT_CTLR_PHY || !CONFIG_BT_CTLR_PHY_2M */ #if defined(CONFIG_BT_CTLR_SMI_TX) #if defined(CONFIG_BT_CTLR_SMI_TX_SETTING) @@ -86,11 +86,11 @@ #define LL_FEAT_BIT_SMI_RX 0 #endif /* !CONFIG_BT_CTLR_SMI_RX */ -#if defined(CONFIG_BT_CTLR_PHY_CODED) +#if defined(CONFIG_BT_CTLR_PHY) && defined(CONFIG_BT_CTLR_PHY_CODED) #define LL_FEAT_BIT_PHY_CODED BIT64(BT_LE_FEAT_BIT_PHY_CODED) -#else /* !CONFIG_BT_CTLR_PHY_CODED */ +#else /* !CONFIG_BT_CTLR_PHY || !CONFIG_BT_CTLR_PHY_CODED */ #define LL_FEAT_BIT_PHY_CODED 0 -#endif /* !CONFIG_BT_CTLR_PHY_CODED */ +#endif /* !CONFIG_BT_CTLR_PHY || !CONFIG_BT_CTLR_PHY_CODED */ #if defined(CONFIG_BT_CTLR_ADV_EXT) #define LL_FEAT_BIT_EXT_ADV BIT64(BT_LE_FEAT_BIT_EXT_ADV) diff --git a/subsys/bluetooth/controller/include/ll_settings.h b/subsys/bluetooth/controller/include/ll_settings.h index c79a4fb1537b..df3835481f3e 100644 --- a/subsys/bluetooth/controller/include/ll_settings.h +++ b/subsys/bluetooth/controller/include/ll_settings.h @@ -1,25 +1,31 @@ /* + * Copyright (c) 2025 Nordic Semiconductor ASA * Copyright (c) 2019 Oticon A/S * * SPDX-License-Identifier: Apache-2.0 */ #if defined(CONFIG_BT_CTLR_VERSION_SETTINGS) +#define LL_VERSION_SETTINGS +#else /* !CONFIG_BT_CTLR_VERSION_SETTINGS */ +#define LL_VERSION_SETTINGS static __attribute__((always_inline)) inline +#endif /* !CONFIG_BT_CTLR_VERSION_SETTINGS */ -uint16_t ll_settings_company_id(void); -uint16_t ll_settings_subversion_number(void); +/* Version Interfaces */ +LL_VERSION_SETTINGS uint16_t ll_settings_company_id(void); +LL_VERSION_SETTINGS uint16_t ll_settings_subversion_number(void); -#else +/* Stable Modulation Index Interfaces */ +bool ll_settings_smi_tx(void); -static inline uint16_t ll_settings_company_id(void) +/* Static inline functions */ +#if !defined(CONFIG_BT_CTLR_VERSION_SETTINGS) +LL_VERSION_SETTINGS uint16_t ll_settings_company_id(void) { return CONFIG_BT_CTLR_COMPANY_ID; } -static inline uint16_t ll_settings_subversion_number(void) +LL_VERSION_SETTINGS uint16_t ll_settings_subversion_number(void) { return CONFIG_BT_CTLR_SUBVERSION_NUMBER; } - -#endif /* CONFIG_BT_CTLR_VERSION_SETTINGS */ - -bool ll_settings_smi_tx(void); +#endif /* !CONFIG_BT_CTLR_VERSION_SETTINGS */ diff --git a/subsys/bluetooth/controller/ll_sw/isoal.c b/subsys/bluetooth/controller/ll_sw/isoal.c index 625edbbb63d7..9d2db83668d3 100644 --- a/subsys/bluetooth/controller/ll_sw/isoal.c +++ b/subsys/bluetooth/controller/ll_sw/isoal.c @@ -151,8 +151,8 @@ static bool isoal_get_time_diff(uint32_t time_before, uint32_t time_after, uint3 { bool valid = false; - LL_ASSERT(time_before <= ISOAL_TIME_WRAPPING_POINT_US); - LL_ASSERT(time_after <= ISOAL_TIME_WRAPPING_POINT_US); + LL_ASSERT_DBG(time_before <= ISOAL_TIME_WRAPPING_POINT_US); + LL_ASSERT_DBG(time_after <= ISOAL_TIME_WRAPPING_POINT_US); if (time_before > time_after) { if (time_before >= ISOAL_TIME_MID_POINT_US && @@ -225,13 +225,13 @@ static void isoal_sink_deallocate(isoal_sink_handle_t hdl) if (hdl < ARRAY_SIZE(isoal_global.sink_allocated)) { isoal_global.sink_allocated[hdl] = ISOAL_ALLOC_STATE_FREE; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } if (hdl < ARRAY_SIZE(isoal_global.sink_state)) { (void)memset(&isoal_global.sink_state[hdl], 0, sizeof(struct isoal_sink)); } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -350,7 +350,7 @@ isoal_status_t isoal_sink_create( session->sdu_sync_const = group_sync_delay; } } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } /* Remember the platform-specific callbacks */ @@ -378,7 +378,7 @@ void isoal_sink_enable(isoal_sink_handle_t hdl) /* Atomically enable */ isoal_global.sink_state[hdl].sdu_production.mode = ISOAL_PRODUCTION_MODE_ENABLED; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -392,7 +392,7 @@ void isoal_sink_disable(isoal_sink_handle_t hdl) /* Atomically disable */ isoal_global.sink_state[hdl].sdu_production.mode = ISOAL_PRODUCTION_MODE_DISABLED; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -441,7 +441,7 @@ static isoal_status_t isoal_rx_allocate_sdu(struct isoal_sink *sink, /* Nothing has been written into buffer yet */ sp->sdu_written = 0; sp->sdu_available = sdu->contents.size; - LL_ASSERT(sdu->contents.size > 0); + LL_ASSERT_ERR(sdu->contents.size > 0); /* Get seq number from session counter */ sdu->sn = session->sn; @@ -568,7 +568,7 @@ static isoal_status_t isoal_rx_buffered_emit_sdu(struct isoal_sink *sink, bool e #endif /* ISOAL_BUFFER_RX_SDUS_ENABLE */ } else { /* Unreachable */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } return err; @@ -653,7 +653,6 @@ static isoal_status_t isoal_rx_append_to_sdu(struct isoal_sink *sink, handle_error_case = (is_end_fragment && (packet_available == 0)); pdu_payload = pdu_meta->pdu->payload + offset; - LL_ASSERT(pdu_payload); /* While there is something left of the packet to consume */ err = ISOAL_STATUS_OK; @@ -880,7 +879,7 @@ static isoal_status_t isoal_rx_unframed_consume(struct isoal_sink *sink, /* Unsupported case */ err = ISOAL_STATUS_ERR_UNSPECIFIED; LOG_ERR("Invalid unframed LLID (%d)", llid); - LL_ASSERT(0); + LL_ASSERT_ERR(0); } break; @@ -1459,7 +1458,8 @@ static void isoal_source_deallocate(isoal_source_handle_t hdl) if (hdl < ARRAY_SIZE(isoal_global.source_state)) { source = &isoal_global.source_state[hdl]; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); + return; } @@ -1477,7 +1477,7 @@ static void isoal_source_deallocate(isoal_source_handle_t hdl) if (hdl < ARRAY_SIZE(isoal_global.source_allocated)) { isoal_global.source_allocated[hdl] = ISOAL_ALLOC_STATE_FREE; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } (void)memset(source, 0, sizeof(struct isoal_source)); @@ -1594,7 +1594,7 @@ void isoal_source_enable(isoal_source_handle_t hdl) /* Atomically enable */ isoal_global.source_state[hdl].pdu_production.mode = ISOAL_PRODUCTION_MODE_ENABLED; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -1608,7 +1608,7 @@ void isoal_source_disable(isoal_source_handle_t hdl) /* Atomically disable */ isoal_global.source_state[hdl].pdu_production.mode = ISOAL_PRODUCTION_MODE_DISABLED; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -1770,7 +1770,7 @@ static isoal_status_t isoal_tx_allocate_pdu(struct isoal_source *source, pp->pdu_written = 0; pp->pdu_available = available_len; pp->pdu_allocated = 1U; - LL_ASSERT(available_len > 0); + LL_ASSERT_ERR(available_len > 0); pp->pdu_cnt++; } @@ -1982,7 +1982,7 @@ static isoal_status_t isoal_tx_unframed_produce(isoal_source_handle_t source_hdl packet_available = tx_sdu->size; sdu_payload = tx_sdu->dbuf; - LL_ASSERT(sdu_payload); + LL_ASSERT_DBG(sdu_payload); zero_length_sdu = (packet_available == 0 && tx_sdu->sdu_state == BT_ISO_SINGLE); @@ -2468,12 +2468,12 @@ static uint16_t isoal_tx_framed_find_correct_tx_event(const struct isoal_source time_diff_valid = isoal_get_time_diff(time_stamp_selected, actual_grp_ref_point, &time_diff); - LL_ASSERT(time_diff_valid); - LL_ASSERT(time_diff > 0); + LL_ASSERT_DBG(time_diff_valid); + LL_ASSERT_DBG(time_diff > 0); /* Time difference must be less than the maximum possible * time-offset of 24-bits. */ - LL_ASSERT(time_diff <= 0x00FFFFFF); + LL_ASSERT_DBG(time_diff <= 0x00FFFFFF); } *payload_number = next_payload_number; @@ -2514,7 +2514,7 @@ static isoal_status_t isoal_tx_framed_produce(isoal_source_handle_t source_hdl, packet_available = tx_sdu->size; sdu_payload = tx_sdu->dbuf; - LL_ASSERT(sdu_payload); + LL_ASSERT_DBG(sdu_payload); zero_length_sdu = (packet_available == 0 && tx_sdu->sdu_state == BT_ISO_SINGLE); @@ -2791,7 +2791,7 @@ static isoal_status_t isoal_tx_framed_event_prepare_handle(isoal_source_handle_t } /* Not possible to recover if allocation or emit fails here*/ - LL_ASSERT(!(err || err_alloc)); + LL_ASSERT_ERR(!(err || err_alloc)); if (pp->payload_number < last_event_payload + 1ULL) { pp->payload_number = last_event_payload + 1ULL; diff --git a/subsys/bluetooth/controller/ll_sw/lll_chan.c b/subsys/bluetooth/controller/ll_sw/lll_chan.c index 213fce38a8f5..e45134144b64 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_chan.c +++ b/subsys/bluetooth/controller/ll_sw/lll_chan.c @@ -349,39 +349,39 @@ void lll_chan_sel_2_ut(void) /* Tests when ISO not supported */ /* Section 3.1 Sample Data 1 (37 used channels) */ m = lll_chan_sel_2(0U, chan_id, chan_map_1, chan_map_1_37_used); - LL_ASSERT(m == 25U); + LL_ASSERT_ERR(m == 25U); m = lll_chan_sel_2(1U, chan_id, chan_map_1, chan_map_1_37_used); - LL_ASSERT(m == 20U); + LL_ASSERT_ERR(m == 20U); m = lll_chan_sel_2(2U, chan_id, chan_map_1, chan_map_1_37_used); - LL_ASSERT(m == 6U); + LL_ASSERT_ERR(m == 6U); m = lll_chan_sel_2(3U, chan_id, chan_map_1, chan_map_1_37_used); - LL_ASSERT(m == 21U); + LL_ASSERT_ERR(m == 21U); /* Section 3.2 Sample Data 2 (9 used channels) */ m = lll_chan_sel_2(6U, chan_id, chan_map_2, chan_map_2_9_used); - LL_ASSERT(m == 23U); + LL_ASSERT_ERR(m == 23U); m = lll_chan_sel_2(7U, chan_id, chan_map_2, chan_map_2_9_used); - LL_ASSERT(m == 9U); + LL_ASSERT_ERR(m == 9U); m = lll_chan_sel_2(8U, chan_id, chan_map_2, chan_map_2_9_used); - LL_ASSERT(m == 34U); + LL_ASSERT_ERR(m == 34U); /* FIXME: Use Sample Data from Spec, if one is added. * Below is a random sample to cover implementation in this file. */ /* Section x.x Sample Data 3 (2 used channels) */ m = lll_chan_sel_2(11U, chan_id, chan_map_3, chan_map_3_2_used); - LL_ASSERT(m == 1U); + LL_ASSERT_ERR(m == 1U); m = lll_chan_sel_2(12U, chan_id, chan_map_3, chan_map_3_2_used); - LL_ASSERT(m == 2U); + LL_ASSERT_ERR(m == 2U); m = lll_chan_sel_2(13U, chan_id, chan_map_3, chan_map_3_2_used); - LL_ASSERT(m == 1U); + LL_ASSERT_ERR(m == 1U); #if defined(CONFIG_BT_CTLR_ISO) uint16_t prn_subevent_lu; @@ -393,164 +393,164 @@ void lll_chan_sel_2_ut(void) prn_s = 56857U ^ chan_id; prn_subevent_lu = prn_s; prn_subevent_se = chan_prn_subevent_se(chan_id, &prn_subevent_lu); - LL_ASSERT(prn_subevent_se == 11710U); + LL_ASSERT_ERR(prn_subevent_se == 11710U); /* BIS subevent 3, event counter 0 */ prn_subevent_se = chan_prn_subevent_se(chan_id, &prn_subevent_lu); - LL_ASSERT(prn_subevent_se == 16649U); + LL_ASSERT_ERR(prn_subevent_se == 16649U); /* BIS subevent 4, event counter 0 */ prn_subevent_se = chan_prn_subevent_se(chan_id, &prn_subevent_lu); - LL_ASSERT(prn_subevent_se == 38198U); + LL_ASSERT_ERR(prn_subevent_se == 38198U); /* Section 3.1 Sample Data 1 (37 used channels) */ /* BIS subevent 1, event counter 0 */ m = lll_chan_iso_event(0U, chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 56857U); - LL_ASSERT(m == 25U); - LL_ASSERT(remap_idx == 25U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 56857U); + LL_ASSERT_ERR(m == 25U); + LL_ASSERT_ERR(remap_idx == 25U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 1U); - LL_ASSERT(m == 1U); + LL_ASSERT_ERR(remap_idx == 1U); + LL_ASSERT_ERR(m == 1U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 16U); - LL_ASSERT(m == 16U); + LL_ASSERT_ERR(remap_idx == 16U); + LL_ASSERT_ERR(m == 16U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 36U); - LL_ASSERT(m == 36U); + LL_ASSERT_ERR(remap_idx == 36U); + LL_ASSERT_ERR(m == 36U); /* BIS subevent 1, event counter 1 */ m = lll_chan_iso_event(1U, chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 1685U); - LL_ASSERT(m == 20U); - LL_ASSERT(remap_idx == 20U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 1685U); + LL_ASSERT_ERR(m == 20U); + LL_ASSERT_ERR(remap_idx == 20U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 36U); - LL_ASSERT(m == 36U); + LL_ASSERT_ERR(remap_idx == 36U); + LL_ASSERT_ERR(m == 36U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 12U); - LL_ASSERT(m == 12U); + LL_ASSERT_ERR(remap_idx == 12U); + LL_ASSERT_ERR(m == 12U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 34U); - LL_ASSERT(m == 34U); + LL_ASSERT_ERR(remap_idx == 34U); + LL_ASSERT_ERR(m == 34U); /* BIS subevent 1, event counter 2 */ m = lll_chan_iso_event(2U, chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 38301U); - LL_ASSERT(m == 6U); - LL_ASSERT(remap_idx == 6U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 38301U); + LL_ASSERT_ERR(m == 6U); + LL_ASSERT_ERR(remap_idx == 6U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 18U); - LL_ASSERT(m == 18U); + LL_ASSERT_ERR(remap_idx == 18U); + LL_ASSERT_ERR(m == 18U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 32U); - LL_ASSERT(m == 32U); + LL_ASSERT_ERR(remap_idx == 32U); + LL_ASSERT_ERR(m == 32U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 21U); - LL_ASSERT(m == 21U); + LL_ASSERT_ERR(remap_idx == 21U); + LL_ASSERT_ERR(m == 21U); /* BIS subevent 1, event counter 3 */ m = lll_chan_iso_event(3U, chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 27475U); - LL_ASSERT(m == 21U); - LL_ASSERT(remap_idx == 21U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 27475U); + LL_ASSERT_ERR(m == 21U); + LL_ASSERT_ERR(remap_idx == 21U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 4U); - LL_ASSERT(m == 4U); + LL_ASSERT_ERR(remap_idx == 4U); + LL_ASSERT_ERR(m == 4U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 22U); - LL_ASSERT(m == 22U); + LL_ASSERT_ERR(remap_idx == 22U); + LL_ASSERT_ERR(m == 22U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_1, chan_map_1_37_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 8U); - LL_ASSERT(m == 8U); + LL_ASSERT_ERR(remap_idx == 8U); + LL_ASSERT_ERR(m == 8U); /* Section 3.2 Sample Data 2 (9 used channels) */ /* BIS subevent 1, event counter 6 */ m = lll_chan_iso_event(6U, chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 10975U); - LL_ASSERT(remap_idx == 4U); - LL_ASSERT(m == 23U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 10975U); + LL_ASSERT_ERR(remap_idx == 4U); + LL_ASSERT_ERR(m == 23U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 7U); - LL_ASSERT(m == 35U); + LL_ASSERT_ERR(remap_idx == 7U); + LL_ASSERT_ERR(m == 35U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 2U); - LL_ASSERT(m == 21U); + LL_ASSERT_ERR(remap_idx == 2U); + LL_ASSERT_ERR(m == 21U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 8U); - LL_ASSERT(m == 36U); + LL_ASSERT_ERR(remap_idx == 8U); + LL_ASSERT_ERR(m == 36U); /* BIS subevent 1, event counter 7 */ m = lll_chan_iso_event(7U, chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 5490U); - LL_ASSERT(remap_idx == 0U); - LL_ASSERT(m == 9U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 5490U); + LL_ASSERT_ERR(remap_idx == 0U); + LL_ASSERT_ERR(m == 9U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 3U); - LL_ASSERT(m == 22U); + LL_ASSERT_ERR(remap_idx == 3U); + LL_ASSERT_ERR(m == 22U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 8U); - LL_ASSERT(m == 36U); + LL_ASSERT_ERR(remap_idx == 8U); + LL_ASSERT_ERR(m == 36U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 5U); - LL_ASSERT(m == 33U); + LL_ASSERT_ERR(remap_idx == 5U); + LL_ASSERT_ERR(m == 33U); /* BIS subevent 1, event counter 8 */ m = lll_chan_iso_event(8U, chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 46970U); - LL_ASSERT(remap_idx == 6U); - LL_ASSERT(m == 34U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 46970U); + LL_ASSERT_ERR(remap_idx == 6U); + LL_ASSERT_ERR(m == 34U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 0U); - LL_ASSERT(m == 9U); + LL_ASSERT_ERR(remap_idx == 0U); + LL_ASSERT_ERR(m == 9U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 5U); - LL_ASSERT(m == 33U); + LL_ASSERT_ERR(remap_idx == 5U); + LL_ASSERT_ERR(m == 33U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_2, chan_map_2_9_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 1U); - LL_ASSERT(m == 10U); + LL_ASSERT_ERR(remap_idx == 1U); + LL_ASSERT_ERR(m == 10U); /* FIXME: Use Sample Data from Spec, if one is added. * Below is a random sample to cover implementation in this file. @@ -558,66 +558,66 @@ void lll_chan_sel_2_ut(void) /* Section x.x Sample Data 3 (2 used channels) */ /* BIS subevent 1, event counter 11 */ m = lll_chan_iso_event(11U, chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 8628U); - LL_ASSERT(remap_idx == 0U); - LL_ASSERT(m == 1U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 8628U); + LL_ASSERT_ERR(remap_idx == 0U); + LL_ASSERT_ERR(m == 1U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 1U); - LL_ASSERT(m == 2U); + LL_ASSERT_ERR(remap_idx == 1U); + LL_ASSERT_ERR(m == 2U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 0U); - LL_ASSERT(m == 1U); + LL_ASSERT_ERR(remap_idx == 0U); + LL_ASSERT_ERR(m == 1U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 1U); - LL_ASSERT(m == 2U); + LL_ASSERT_ERR(remap_idx == 1U); + LL_ASSERT_ERR(m == 2U); /* BIS subevent 1, event counter 12 */ m = lll_chan_iso_event(12U, chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 34748U); - LL_ASSERT(remap_idx == 1U); - LL_ASSERT(m == 2U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 34748U); + LL_ASSERT_ERR(remap_idx == 1U); + LL_ASSERT_ERR(m == 2U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 0U); - LL_ASSERT(m == 1U); + LL_ASSERT_ERR(remap_idx == 0U); + LL_ASSERT_ERR(m == 1U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 1U); - LL_ASSERT(m == 2U); + LL_ASSERT_ERR(remap_idx == 1U); + LL_ASSERT_ERR(m == 2U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 0U); - LL_ASSERT(m == 1U); + LL_ASSERT_ERR(remap_idx == 0U); + LL_ASSERT_ERR(m == 1U); /* BIS subevent 1, event counter 13 */ m = lll_chan_iso_event(13U, chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT((prn_s ^ chan_id) == 22072U); - LL_ASSERT(remap_idx == 0U); - LL_ASSERT(m == 1U); + LL_ASSERT_ERR((prn_s ^ chan_id) == 22072U); + LL_ASSERT_ERR(remap_idx == 0U); + LL_ASSERT_ERR(m == 1U); /* BIS subvent 2 */ m = lll_chan_iso_subevent(chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 1U); - LL_ASSERT(m == 2U); + LL_ASSERT_ERR(remap_idx == 1U); + LL_ASSERT_ERR(m == 2U); /* BIS subvent 3 */ m = lll_chan_iso_subevent(chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 0U); - LL_ASSERT(m == 1U); + LL_ASSERT_ERR(remap_idx == 0U); + LL_ASSERT_ERR(m == 1U); /* BIS subvent 4 */ m = lll_chan_iso_subevent(chan_id, chan_map_3, chan_map_3_2_used, &prn_s, &remap_idx); - LL_ASSERT(remap_idx == 1U); - LL_ASSERT(m == 2U); + LL_ASSERT_ERR(remap_idx == 1U); + LL_ASSERT_ERR(m == 2U); #endif /* CONFIG_BT_CTLR_ISO */ } diff --git a/subsys/bluetooth/controller/ll_sw/lll_common.c b/subsys/bluetooth/controller/ll_sw/lll_common.c index c6c561dbb76d..96861aa72010 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_common.c +++ b/subsys/bluetooth/controller/ll_sw/lll_common.c @@ -77,7 +77,7 @@ void lll_resume(void *param) next = param; err = lll_prepare_resolve(next->is_abort_cb, next->abort_cb, next->prepare_cb, &next->prepare_param, next->is_resume, 1U); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } #if defined(CONFIG_BT_CTLR_JIT_SCHEDULING) diff --git a/subsys/bluetooth/controller/ll_sw/lll_scan.h b/subsys/bluetooth/controller/ll_sw/lll_scan.h index db0f08a182e1..b9633f899383 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_scan.h +++ b/subsys/bluetooth/controller/ll_sw/lll_scan.h @@ -17,6 +17,14 @@ struct lll_scan { uint8_t adv_addr[BDADDR_SIZE]; uint32_t conn_win_offset_us; uint16_t conn_timeout; + +#if defined(CONFIG_BT_CTLR_SCHED_ADVANCED) + /* Stores prepare parameters for deferred mayfly execution. + * This prevents use-after-release issues by ensuring the parameters + * remain valid until execution. + */ + struct lll_prepare_param prepare_param; +#endif /* CONFIG_BT_CTLR_SCHED_ADVANCED */ #endif /* CONFIG_BT_CENTRAL */ uint8_t state:1; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c index eb1116c987f7..ba6487b53534 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c @@ -110,7 +110,7 @@ uint32_t cntr_start(void) uint32_t cntr_stop(void) { - LL_ASSERT(_refcount); + LL_ASSERT_ERR(_refcount); if (--_refcount) { return 1; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ecb.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ecb.c index 2398bdc44fd7..38b70c491d7d 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ecb.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ecb.c @@ -225,7 +225,7 @@ static void isr_ecb(const void *arg) } else { - LL_ASSERT(false); + LL_ASSERT_DBG(false); } } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/mayfly.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/mayfly.c index 531cbd5b2412..73408b234544 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/mayfly.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/mayfly.c @@ -42,7 +42,7 @@ void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enable) break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } @@ -62,7 +62,7 @@ uint32_t mayfly_is_enabled(uint8_t caller_id, uint8_t callee_id) return irq_is_enabled(HAL_SWI_JOB_IRQ); default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -120,7 +120,7 @@ void mayfly_pend(uint8_t caller_id, uint8_t callee_id) break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index 90a0945f5a19..7056f020bc28 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -10,6 +10,7 @@ #include #include +#include #include #include "util/mem.h" @@ -221,7 +222,11 @@ void radio_reset(void) RADIO_TIMING_RU_Msk; #endif /* !CONFIG_BT_CTLR_TIFS_HW */ +#if defined(CONFIG_NRF_SYS_EVENT) + (void)nrf_sys_event_request_global_constlat(); +#else /* !CONFIG_NRF_SYS_EVENT */ NRF_POWER->TASKS_CONSTLAT = 1U; +#endif /* !CONFIG_NRF_SYS_EVENT */ #endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */ #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) @@ -312,7 +317,7 @@ void radio_tx_power_set(int8_t power) value = hal_radio_tx_power_value(power); NRF_RADIO->TXPOWER = value; -#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#elif defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) uint32_t value; /* NOTE: TXPOWER register only accepts upto 0dBm, hence use the HAL @@ -323,12 +328,12 @@ void radio_tx_power_set(int8_t power) NRF_RADIO->TXPOWER = value; hal_radio_tx_power_high_voltage_set(power); -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ /* NOTE: valid value range is passed by Kconfig define. */ NRF_RADIO->TXPOWER = (uint32_t)power; -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tx_power_max_set(void) @@ -346,25 +351,25 @@ int8_t radio_tx_power_min_get(void) int8_t radio_tx_power_max_get(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) return RADIO_TXPOWER_TXPOWER_Pos3dBm; -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ return (int8_t)hal_radio_tx_power_max_get(); -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ } int8_t radio_tx_power_floor(int8_t power) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) /* NOTE: TXPOWER register only accepts upto 0dBm, +3dBm permitted by * use of high voltage being set for radio when TXPOWER register is set. */ if (power >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { return RADIO_TXPOWER_TXPOWER_Pos3dBm; } -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ return (int8_t)hal_radio_tx_power_floor(power); } @@ -422,7 +427,7 @@ void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags) bits_s1 = RADIO_PKT_CONF_LENGTH_8BIT - bits_len; #elif defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ - defined(CONFIG_SOC_COMPATIBLE_NRF53X) || \ + defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || \ defined(CONFIG_SOC_COMPATIBLE_NRF54LX) extra = 0U; @@ -520,7 +525,7 @@ uint32_t radio_rx_chain_delay_get(uint8_t phy, uint8_t flags) void radio_rx_enable(void) { #if !defined(CONFIG_BT_CTLR_TIFS_HW) -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -533,7 +538,7 @@ void radio_rx_enable(void) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET || CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RXEN); @@ -542,7 +547,7 @@ void radio_rx_enable(void) void radio_tx_enable(void) { #if !defined(CONFIG_BT_CTLR_TIFS_HW) -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -555,7 +560,7 @@ void radio_tx_enable(void) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET || CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN); @@ -934,13 +939,13 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla * time-stamp. */ hal_radio_end_time_capture_ppi_config(); -#if !defined(CONFIG_SOC_COMPATIBLE_NRF53X) && !defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#if !defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) && !defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* The function is not called for nRF5340 single timer configuration because * HAL_SW_SWITCH_TIMER_CLEAR_PPI is equal to HAL_RADIO_END_TIME_CAPTURE_PPI, * so channel is already enabled. */ hal_radio_nrf_ppi_channels_enable(BIT(HAL_RADIO_END_TIME_CAPTURE_PPI)); -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ sw_tifs_toggle += 1U; @@ -1355,38 +1360,38 @@ void radio_tmr_rx_status_reset(void) void radio_tmr_tx_enable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#else /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI) hal_radio_enable_on_tick_ppi_config_and_enable(1U); #endif /* HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tmr_rx_enable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#else /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI) hal_radio_enable_on_tick_ppi_config_and_enable(0U); #endif /* HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tmr_tx_disable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_TXEN); -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tmr_rx_disable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_RXEN); -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tmr_tifs_set(uint32_t tifs) @@ -1622,7 +1627,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t ticks_start) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) last_pdu_end_us_init(latency_us); #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -1635,7 +1640,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t ticks_start) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET || CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ return remainder_us; @@ -1652,7 +1657,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) */ start_us -= last_pdu_end_us; #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -1665,7 +1670,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET || CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ /* start_us could be the current count in the timer */ @@ -1788,7 +1793,11 @@ void radio_tmr_stop(void) #endif /* !CONFIG_BT_CTLR_TIFS_HW */ #if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#if defined(CONFIG_NRF_SYS_EVENT) + (void)nrf_sys_event_release_global_constlat(); +#else /* !CONFIG_NRF_SYS_EVENT */ NRF_POWER->TASKS_LOWPWR = 1U; +#endif /* !CONFIG_NRF_SYS_EVENT */ #endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */ } @@ -1867,13 +1876,14 @@ void radio_tmr_end_capture(void) * hal_sw_switch_timer_clear_ppi_config() and sw_switch(). There is no need to * configure the channel again in this function. */ -#if (!defined(CONFIG_SOC_COMPATIBLE_NRF53X) && !defined(CONFIG_SOC_COMPATIBLE_NRF54LX)) || \ - ((defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX)) && \ +#if (!defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) && !defined(CONFIG_SOC_COMPATIBLE_NRF54LX)) || \ + ((defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) || \ + defined(CONFIG_SOC_COMPATIBLE_NRF54LX)) && \ !defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)) hal_radio_end_time_capture_ppi_config(); hal_radio_nrf_ppi_channels_enable(BIT(HAL_RADIO_END_TIME_CAPTURE_PPI)); -#endif /* (!CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX) || - * ((CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_COMPATIBLE_NRF54LX) && +#endif /* (!CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET && !CONFIG_SOC_COMPATIBLE_NRF54LX) || + * ((CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET || CONFIG_SOC_COMPATIBLE_NRF54LX) && * !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) */ } @@ -2104,10 +2114,14 @@ static void *radio_ccm_ext_rx_pkt_set(struct ccm *cnf, uint8_t phy, uint8_t pdu_ NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; - mode = (CCM_MODE_MODE_Decryption << CCM_MODE_MODE_Pos) & + /* Select the CCM decryption mode for the SoC */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + /* NOTE: Use fast decryption as rx data is decrypt after payload is received, compared to + * decrypting in parallel with radio reception of address in nRF51/nRF52/nRF53. + */ + mode = (CCM_MODE_MODE_FastDecryption << CCM_MODE_MODE_Pos) & CCM_MODE_MODE_Msk; -#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* Enable CCM Protocol Mode Bluetooth LE */ mode |= (CCM_MODE_PROTOCOL_Ble << CCM_MODE_PROTOCOL_Pos) & CCM_MODE_PROTOCOL_Msk; @@ -2116,21 +2130,30 @@ static void *radio_ccm_ext_rx_pkt_set(struct ccm *cnf, uint8_t phy, uint8_t pdu_ mode |= (CCM_MODE_MACLEN_M4 << CCM_MODE_MACLEN_Pos) & CCM_MODE_MACLEN_Msk; -#elif !defined(CONFIG_SOC_SERIES_NRF51X) +#elif defined(CONFIG_SOC_COMPATIBLE_NRF52X) || defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) + mode = (CCM_MODE_MODE_Decryption << CCM_MODE_MODE_Pos) & + CCM_MODE_MODE_Msk; + /* Enable CCM support for 8-bit length field PDUs. */ mode |= (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos) & CCM_MODE_LENGTH_Msk; -#endif /* !CONFIG_SOC_SERIES_NRF51X */ + +#elif defined(CONFIG_SOC_SERIES_NRF51X) + mode = (CCM_MODE_MODE_Decryption << CCM_MODE_MODE_Pos) & + CCM_MODE_MODE_Msk; + +#else +#error "H/w accelerated decryption unsupported." +#endif /* Select CCM data rate based on current PHY in use. */ switch (phy) { default: case PHY_1M: -#if !defined(CONFIG_SOC_SERIES_NRF51X) - mode |= (CCM_MODE_DATARATE_1Mbit << - CCM_MODE_DATARATE_Pos) & +#if !defined(CONFIG_SOC_SERIES_NRF51X) && !defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + mode |= (CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos) & CCM_MODE_DATARATE_Msk; -#endif /* !CONFIG_SOC_SERIES_NRF51X */ +#endif /* !CONFIG_SOC_SERIES_NRF51X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ if (false) { @@ -2153,11 +2176,10 @@ static void *radio_ccm_ext_rx_pkt_set(struct ccm *cnf, uint8_t phy, uint8_t pdu_ break; case PHY_2M: -#if !defined(CONFIG_SOC_SERIES_NRF51X) - mode |= (CCM_MODE_DATARATE_2Mbit << - CCM_MODE_DATARATE_Pos) & +#if !defined(CONFIG_SOC_SERIES_NRF51X) && !defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + mode |= (CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos) & CCM_MODE_DATARATE_Msk; -#endif /* !CONFIG_SOC_SERIES_NRF51X */ +#endif /* !CONFIG_SOC_SERIES_NRF51X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ hal_trigger_crypt_ppi_config(); hal_radio_nrf_ppi_channels_enable(BIT(HAL_TRIGGER_CRYPT_PPI)); @@ -2167,9 +2189,10 @@ static void *radio_ccm_ext_rx_pkt_set(struct ccm *cnf, uint8_t phy, uint8_t pdu_ #if defined(CONFIG_BT_CTLR_PHY_CODED) #if defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED) case PHY_CODED: - mode |= (CCM_MODE_DATARATE_125Kbps << - CCM_MODE_DATARATE_Pos) & +#if !defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + mode |= (CCM_MODE_DATARATE_125Kbps << CCM_MODE_DATARATE_Pos) & CCM_MODE_DATARATE_Msk; +#endif /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ NRF_CCM->RATEOVERRIDE = (CCM_RATEOVERRIDE_RATEOVERRIDE_500Kbps << @@ -2336,22 +2359,11 @@ static void *radio_ccm_ext_tx_pkt_set(struct ccm *cnf, uint8_t pdu_type, void *p NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; + /* Select the CCM encryption mode for the SoC */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) mode = (CCM_MODE_MODE_Encryption << CCM_MODE_MODE_Pos) & CCM_MODE_MODE_Msk; -#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ - defined(CONFIG_SOC_COMPATIBLE_NRF53X) - /* Enable CCM support for 8-bit length field PDUs. */ - mode |= (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos) & - CCM_MODE_LENGTH_Msk; - - /* NOTE: use fastest data rate as tx data needs to be prepared before - * radio Tx on any PHY. - */ - mode |= (CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos) & - CCM_MODE_DATARATE_Msk; - -#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* Enable CCM Protocol Mode Bluetooth LE */ mode |= (CCM_MODE_PROTOCOL_Ble << CCM_MODE_PROTOCOL_Pos) & CCM_MODE_PROTOCOL_Msk; @@ -2365,6 +2377,27 @@ static void *radio_ccm_ext_tx_pkt_set(struct ccm *cnf, uint8_t pdu_type, void *p /* Enable CCM MAC Length 4 bytes */ mode |= (CCM_MODE_MACLEN_M4 << CCM_MODE_MACLEN_Pos) & CCM_MODE_MACLEN_Msk; + +#elif defined(CONFIG_SOC_COMPATIBLE_NRF52X) || defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) + mode = (CCM_MODE_MODE_Encryption << CCM_MODE_MODE_Pos) & + CCM_MODE_MODE_Msk; + + /* Enable CCM support for 8-bit length field PDUs. */ + mode |= (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos) & + CCM_MODE_LENGTH_Msk; + + /* NOTE: use fastest data rate as tx data needs to be prepared before + * radio Tx on any PHY. + */ + mode |= (CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos) & + CCM_MODE_DATARATE_Msk; + +#elif defined(CONFIG_SOC_SERIES_NRF51X) + mode = (CCM_MODE_MODE_Encryption << CCM_MODE_MODE_Pos) & + CCM_MODE_MODE_Msk; + +#else +#error "H/w accelerated encryption unsupported." #endif NRF_CCM->MODE = mode; @@ -2529,7 +2562,48 @@ void radio_ccm_disable(void) #endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ #if defined(CONFIG_BT_CTLR_PRIVACY) +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +struct aar_job_ptr { + void *ptr; + struct { + uint32_t length:24; + uint32_t attribute:8; + } __packed; +} __packed; + +#define AAR_JOB_PTR_ATTRIBUTE_HASH 11U +#define AAR_JOB_PTR_ATTRIBUTE_PRAND 12U +#define AAR_JOB_PTR_ATTRIBUTE_IRK 13U +#define AAR_JOB_PTR_ATTRIBUTE_INDEX 11U + +#define AAR_JOB_OUT_MAX_RESOLVED 1U + +#define AAR_IRK_SIZE 16U + +#define RADIO_PACKET_PTR_TO_PDU_OFFSET 3U + +#define BDADDR_HASH_OFFSET 0U +#define BDADDR_HASH_SIZE 3U +#define BDADDR_PRND_OFFSET 3U +#define BDADDR_PRND_SIZE 3U + +/* AAR HAL global memory referenced by the h/w peripheral and its DMA */ +static struct { + /* Index of the IRK match in the AAR job list, on successful resolution */ + uint32_t status; + + /* Input AAR job list; list of Hash, Prand, IRKs and a terminating empty job entry */ + struct aar_job_ptr in[CONFIG_BT_CTLR_RL_SIZE + 3]; + + /* Output AAR job list of one entry */ + struct aar_job_ptr out[AAR_JOB_OUT_MAX_RESOLVED]; + + /* NOTE: Refer to the AAR section in the SoC product specification for details */ +} aar_job; + +#else /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ static uint8_t MALIGN(4) _aar_scratch[3]; +#endif /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ void radio_ar_configure(uint32_t nirk, void *irk, uint8_t flags) { @@ -2566,10 +2640,57 @@ void radio_ar_configure(uint32_t nirk, void *irk, uint8_t flags) NRF_AAR->ENABLE = (AAR_ENABLE_ENABLE_Enabled << AAR_ENABLE_ENABLE_Pos) & AAR_ENABLE_ENABLE_Msk; + +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + /* Input, Resolvable Address Hash offset in the legacy or extended advertising PDU. + * Radio packet pointer offset by 3 compared to legacy AAR in nRF51/52/53 SoCs that took + * Radio packet pointer value. + */ + aar_job.in[0].ptr = (uint8_t *)addrptr + RADIO_PACKET_PTR_TO_PDU_OFFSET + + BDADDR_HASH_OFFSET; + aar_job.in[0].length = BDADDR_HASH_SIZE; + aar_job.in[0].attribute = AAR_JOB_PTR_ATTRIBUTE_HASH; + + /* Input, Resolvable Address Random offset in the legacy or extended advertising PDU. + * Radio packet pointer offset by 3 compared to legacy AAR in nRF51/52/53 SoCs that took + * Radio packet pointer, plus offset of the 24-bit random in the legacy or extended + * advertising PDU after the 24-bit Hash in the Resolvable Address. + */ + aar_job.in[1].ptr = (uint8_t *)addrptr + RADIO_PACKET_PTR_TO_PDU_OFFSET + + BDADDR_PRND_OFFSET; + aar_job.in[1].length = BDADDR_PRND_SIZE; + aar_job.in[1].attribute = AAR_JOB_PTR_ATTRIBUTE_PRAND; + + /* Input, list of IRKs used for resolution */ + for (uint32_t i = 0; i < nirk; i++) { + aar_job.in[2U + i].ptr = (void *)(((uint8_t *)irk) + (AAR_IRK_SIZE * i)); + aar_job.in[2U + i].length = AAR_IRK_SIZE; + aar_job.in[2U + i].attribute = AAR_JOB_PTR_ATTRIBUTE_IRK; + } + + /* A terminating empty job entry */ + aar_job.in[2U + nirk].ptr = 0U; + aar_job.in[2U + nirk].length = 0U; + aar_job.in[2U + nirk].attribute = 0U; + + /* Reset match index to invalid value ( >= CONFIG_BT_CTLR_RL_SIZE ) */ + aar_job.status = UINT32_MAX; + + /* Output, single job entry that populates the `status` value with match index */ + aar_job.out[0].ptr = &aar_job.status; + aar_job.out[0].length = sizeof(aar_job.status); + aar_job.out[0].attribute = AAR_JOB_PTR_ATTRIBUTE_INDEX; + + NRF_AAR->IN.PTR = (uint32_t)&aar_job.in[0]; + NRF_AAR->OUT.PTR = (uint32_t)&aar_job.out[0]; + NRF_AAR->MAXRESOLVED = AAR_JOB_OUT_MAX_RESOLVED; + +#else /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ NRF_AAR->NIRK = nirk; NRF_AAR->IRKPTR = (uint32_t)irk; NRF_AAR->ADDRPTR = addrptr; NRF_AAR->SCRATCHPTR = (uint32_t)&_aar_scratch[0]; +#endif /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_END); nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_RESOLVED); @@ -2584,7 +2705,11 @@ void radio_ar_configure(uint32_t nirk, void *irk, uint8_t flags) uint32_t radio_ar_match_get(void) { +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + return aar_job.status; +#else /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ return NRF_AAR->STATUS; +#endif /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_ar_status_reset(void) @@ -2627,7 +2752,25 @@ uint8_t radio_ar_resolve(const uint8_t *addr) NRF_AAR->ENABLE = (AAR_ENABLE_ENABLE_Enabled << AAR_ENABLE_ENABLE_Pos) & AAR_ENABLE_ENABLE_Msk; +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + /* Input, Resolvable Address Hash offset in the supplied address buffer */ + aar_job.in[0].ptr = (void *)&addr[BDADDR_HASH_OFFSET]; + + /* Input, Resolvable Address Prand offset in the supplied address buffer */ + aar_job.in[1].ptr = (void *)&addr[BDADDR_PRND_OFFSET]; + + /* Reset match index to invalid value ( >= CONFIG_BT_CTLR_RL_SIZE ) */ + aar_job.status = UINT32_MAX; + + /* NOTE: Other `aar_job` structure members are initialized in `radio_ar_configure()` */ + + NRF_AAR->IN.PTR = (uint32_t)&aar_job.in[0]; + NRF_AAR->OUT.PTR = (uint32_t)&aar_job.out[0]; + NRF_AAR->MAXRESOLVED = AAR_JOB_OUT_MAX_RESOLVED; + +#else /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ NRF_AAR->ADDRPTR = (uint32_t)addr - 3; +#endif /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_END); nrf_aar_event_clear(NRF_AAR, NRF_AAR_EVENT_RESOLVED); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h index f01f9859db4b..1b15f41c4080 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h @@ -40,6 +40,7 @@ #include #include "radio_nrf5340.h" #elif defined(CONFIG_SOC_SERIES_NRF54LX) +#include #include "radio_nrf54lx.h" #elif defined(CONFIG_BOARD_NRF52_BSIM) #include "radio_sim_nrf52.h" @@ -47,6 +48,7 @@ #include #include "radio_sim_nrf5340.h" #elif defined(CONFIG_BOARD_NRF54L15BSIM_NRF54L15_CPUAPP) +#include #include "radio_sim_nrf54l.h" #else #error "Unsupported SoC." @@ -54,7 +56,6 @@ #if defined(CONFIG_BT_CTLR_NRF_GRTC) #include -#include #else /* !CONFIG_BT_CTLR_NRF_GRTC */ #include #endif /* !CONFIG_BT_CTLR_NRF_GRTC */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h index 047e3ea24878..3a8206d79764 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h @@ -398,6 +398,9 @@ #define CCM_MODE_DATARATE_500Kbps CCM_MODE_DATARATE_500Kbit #define CCM_RATEOVERRIDE_RATEOVERRIDE_500Kbps CCM_RATEOVERRIDE_RATEOVERRIDE_500Kbit +/* HAL abstraction of AAR h/w */ +#define NRF_AAR NRF_AAR00 + static inline void hal_radio_reset(void) { /* TODO: Add any required setup for each radio event diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index 11bb973994b4..1085f72f0b98 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -106,17 +106,17 @@ static inline void hal_event_timer_start_ppi_config(void) nrf_grtc_publish_set(NRF_GRTC, HAL_CNTR_GRTC_EVENT_COMPARE_RADIO, HAL_EVENT_TIMER_START_PPI); - /* Enable same DPPI in Peripheral domain */ - nrf_dppi_channels_enable(NRF_DPPIC20, - BIT(HAL_EVENT_TIMER_START_PPI)); + /* Setup PPIB receive publish */ + nrf_ppib_publish_set(NRF_PPIB11, HAL_PPIB_RECEIVE_EVENT_TIMER_START_PPI, + HAL_EVENT_TIMER_START_PPI); /* Setup PPIB send subscribe */ nrf_ppib_subscribe_set(NRF_PPIB21, HAL_PPIB_SEND_EVENT_TIMER_START_PPI, HAL_EVENT_TIMER_START_PPI); - /* Setup PPIB receive publish */ - nrf_ppib_publish_set(NRF_PPIB11, HAL_PPIB_RECEIVE_EVENT_TIMER_START_PPI, - HAL_EVENT_TIMER_START_PPI); + /* Enable same DPPI in Peripheral domain */ + nrf_dppi_channels_enable(NRF_DPPIC20, + BIT(HAL_EVENT_TIMER_START_PPI)); #else /* !CONFIG_BT_CTLR_NRF_GRTC */ nrf_rtc_publish_set(NRF_RTC, NRF_RTC_EVENT_COMPARE_2, HAL_EVENT_TIMER_START_PPI); @@ -148,22 +148,22 @@ static inline void hal_radio_ready_time_capture_ppi_config(void) */ static inline void hal_trigger_crypt_ppi_config(void) { +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_PAYLOAD, HAL_TRIGGER_CRYPT_PPI); nrf_ccm_subscribe_set(NRF_CCM, NRF_CCM_TASK_START, HAL_TRIGGER_CRYPT_PPI); -#if !defined(CONFIG_SOC_COMPATIBLE_NRF54LX) - nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS, HAL_TRIGGER_CRYPT_PPI); + /* Setup PPIB receive publish */ + nrf_ppib_publish_set(NRF_PPIB00, HAL_PPIB_RECEIVE_TRIGGER_CRYPT_PPI, HAL_TRIGGER_CRYPT_PPI); -#else /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ - nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_PAYLOAD, HAL_TRIGGER_CRYPT_PPI); + /* Setup PPIB send subscribe */ + nrf_ppib_subscribe_set(NRF_PPIB10, HAL_PPIB_SEND_TRIGGER_CRYPT_PPI, HAL_TRIGGER_CRYPT_PPI); /* Enable same DPPI in MCU domain */ nrf_dppi_channels_enable(NRF_DPPIC00, BIT(HAL_TRIGGER_CRYPT_PPI)); - /* Setup PPIB send subscribe */ - nrf_ppib_subscribe_set(NRF_PPIB10, HAL_PPIB_SEND_TRIGGER_CRYPT_PPI, HAL_TRIGGER_CRYPT_PPI); - - /* Setup PPIB receive publish */ - nrf_ppib_publish_set(NRF_PPIB00, HAL_PPIB_RECEIVE_TRIGGER_CRYPT_PPI, HAL_TRIGGER_CRYPT_PPI); +#else /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS, HAL_TRIGGER_CRYPT_PPI); + nrf_ccm_subscribe_set(NRF_CCM, NRF_CCM_TASK_START, HAL_TRIGGER_CRYPT_PPI); #endif /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ } @@ -226,6 +226,17 @@ static inline void hal_trigger_aar_ppi_config(void) { nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH, HAL_TRIGGER_AAR_PPI); nrf_aar_subscribe_set(NRF_AAR, NRF_AAR_TASK_START, HAL_TRIGGER_AAR_PPI); + +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + /* Enable same DPPI in MCU domain */ + nrf_dppi_channels_enable(NRF_DPPIC00, BIT(HAL_TRIGGER_AAR_PPI)); + + /* Setup PPIB send subscribe */ + nrf_ppib_subscribe_set(NRF_PPIB10, HAL_PPIB_SEND_TRIGGER_AAR_PPI, HAL_TRIGGER_AAR_PPI); + + /* Setup PPIB receive publish */ + nrf_ppib_publish_set(NRF_PPIB00, HAL_PPIB_RECEIVE_TRIGGER_AAR_PPI, HAL_TRIGGER_AAR_PPI); +#endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */ } #endif /* CONFIG_BT_CTLR_PRIVACY */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h index 3c9a9e6949b3..3a49b97e7b26 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi_resources.h @@ -60,19 +60,25 @@ */ #if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) #define HAL_TRIGGER_CRYPT_PPI 7 -#else /* CONFIG_SOC_COMPATIBLE_NRF54LX */ -#define HAL_TRIGGER_CRYPT_PPI HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI -#endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */ #define HAL_PPIB_SEND_TRIGGER_CRYPT_PPI \ _CONCAT(NRF_PPIB_TASK_SEND_, HAL_TRIGGER_CRYPT_PPI) #define HAL_PPIB_RECEIVE_TRIGGER_CRYPT_PPI \ _CONCAT(NRF_PPIB_EVENT_RECEIVE_, HAL_TRIGGER_CRYPT_PPI) +#else /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#define HAL_TRIGGER_CRYPT_PPI HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI +#endif /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ /******************************************************************************* * Trigger automatic address resolution on Bit counter match: * wire the RADIO EVENTS_BCMATCH event to the AAR TASKS_START task. */ #define HAL_TRIGGER_AAR_PPI 6 +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#define HAL_PPIB_SEND_TRIGGER_AAR_PPI \ + _CONCAT(NRF_PPIB_TASK_SEND_, HAL_TRIGGER_AAR_PPI) +#define HAL_PPIB_RECEIVE_TRIGGER_AAR_PPI \ + _CONCAT(NRF_PPIB_EVENT_RECEIVE_, HAL_TRIGGER_AAR_PPI) +#endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */ #if defined(CONFIG_BT_CTLR_PHY_CODED) && \ defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf54l.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf54l.h index 324f2c8edb3f..8987031db5f1 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf54l.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf54l.h @@ -392,6 +392,9 @@ #define CCM_MODE_DATARATE_500Kbps CCM_MODE_DATARATE_500Kbit #define CCM_RATEOVERRIDE_RATEOVERRIDE_500Kbps CCM_RATEOVERRIDE_RATEOVERRIDE_500Kbit +/* HAL abstraction of AAR h/w */ +#define NRF_AAR NRF_AAR00 + static inline void hal_radio_reset(void) { /* TODO: Add any required setup for each radio event diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c index 9ebafae2e9c4..e46ba7f6f62f 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c @@ -38,10 +38,10 @@ uint8_t hal_ticker_instance0_caller_id_get(uint8_t user_id) { uint8_t caller_id; - LL_ASSERT(user_id < sizeof(caller_id_lut)); + LL_ASSERT_DBG(user_id < sizeof(caller_id_lut)); caller_id = caller_id_lut[user_id]; - LL_ASSERT(caller_id != TICKER_CALL_ID_NONE); + LL_ASSERT_DBG(caller_id != TICKER_CALL_ID_NONE); return caller_id; } @@ -73,7 +73,7 @@ void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t ch break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } break; @@ -96,7 +96,7 @@ void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t ch break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } break; @@ -119,7 +119,7 @@ void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t ch break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } break; @@ -157,7 +157,7 @@ void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t ch break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } break; @@ -181,13 +181,13 @@ void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t ch break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index b44847c05850..0bf5d1772f1e 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -62,7 +62,7 @@ static struct { /* FIXME: This could probably use a chosen entropy device instead on relying on * the nodelabel being the same as for the old nrf rng. */ -static const struct device *const dev_entropy = DEVICE_DT_GET(DT_NODELABEL(rng)); +static const struct device *const dev_entropy = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy)); #endif /* CONFIG_ENTROPY_HAS_DRIVER */ static int init_reset(void); @@ -461,7 +461,7 @@ void lll_disable(void *param) if (event.curr.abort_cb && event.curr.param) { event.curr.abort_cb(NULL, event.curr.param); } else { - LL_ASSERT(!param); + LL_ASSERT_ERR(!param); } } { @@ -519,12 +519,12 @@ int lll_done(void *param) /* Assert if param supplied without a pending prepare to cancel. */ next = ull_prepare_dequeue_get(); - LL_ASSERT(!param || next); + LL_ASSERT_ERR(!param || next); /* check if current LLL event is done */ if (!param) { /* Reset current event instance */ - LL_ASSERT(event.curr.abort_cb); + LL_ASSERT_ERR(event.curr.abort_cb); event.curr.abort_cb = NULL; param = event.curr.param; @@ -567,7 +567,7 @@ int lll_done(void *param) lll_done_score(param, result); extra = ull_event_done_extra_get(); - LL_ASSERT(extra); + LL_ASSERT_ERR(extra); /* Set result in done extra data - type was set by the role */ extra->result = result; @@ -575,7 +575,7 @@ int lll_done(void *param) /* Let ULL know about LLL event done */ evdone = ull_event_done(ull); - LL_ASSERT(evdone); + LL_ASSERT_ERR(evdone); return 0; } @@ -583,7 +583,7 @@ int lll_done(void *param) #if defined(CONFIG_BT_CTLR_LOW_LAT_ULL_DONE) void lll_done_ull_inc(void) { - LL_ASSERT(event.done.ull_count != event.done.lll_count); + LL_ASSERT_ERR(event.done.ull_count != event.done.lll_count); event.done.ull_count++; } #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ @@ -623,7 +623,7 @@ void lll_abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); lll_done(param); } @@ -681,7 +681,7 @@ void lll_chan_set(uint32_t chan) } else if (chan < 40) { radio_freq_chan_set(28 + ((chan - 11) * 2U)); } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } break; } @@ -805,7 +805,7 @@ void lll_isr_cleanup(void *param) radio_stop(); err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); lll_done(NULL); } @@ -822,7 +822,7 @@ void lll_isr_early_abort(void *param) } err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); lll_done(NULL); } @@ -852,16 +852,41 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, ticks_at_preempt_next = ready->prepare_param.ticks_at_expire; diff = ticker_ticks_diff_get(ticks_at_preempt_min, ticks_at_preempt_next); + /* If the enqueued prepare is a resume or current ready prepare is shorter, then we + * should pick current ready prepare for setting up the prepare timeout. + */ if (is_resume || ((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U)) { ticks_at_preempt_min = ticks_at_preempt_next; if (&ready->prepare_param != prepare_param) { + /* There is a shorter prepare in the pipeline */ ready_short = ready; + } else { + /* It is the same prepare in the pipeline being enqueued. + * This can happen executing `lll_done()`. + * Hence, we should ignore it being the `first` that setup the + * preempt timeout and also it has already setup the preempt + * timeout, refer to `preempt_ticker_start()` for details. + * + * We also set the `ready` to NULL as it is the same ready, the one + * being enqueued. This help short circuit a related assertion check + * later in this function. + */ + ready = NULL; } } else { ready = NULL; idx_backup = UINT8_MAX; } + /* Loop and find any short prepare present out-of-order in the prepare pipeline. + * + * NOTE: This loop is O(n), where n is number of items in prepare pipeline present + * before a short prepare was enqueued in to the FIFO. + * Use of ordered linked list implementation has show improved lower latencies + * and less CPU use. + * TODO: Replace use of FIFO for prepare pipeline with ordered linked list + * implementation. + */ do { struct lll_event *ready_next; @@ -900,7 +925,7 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, /* Store the next prepare for deferred call */ next = ull_prepare_enqueue(is_abort_cb, abort_cb, prepare_param, prepare_cb, is_resume); - LL_ASSERT(next); + LL_ASSERT_ERR(next); #if !defined(CONFIG_BT_CTLR_LOW_LAT) if (is_resume || prepare_param->defer) { @@ -918,8 +943,8 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, /* Start the preempt timeout */ ret = preempt_ticker_start(first, ready, next); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); #else /* CONFIG_BT_CTLR_LOW_LAT */ next = NULL; @@ -941,7 +966,7 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, /* check if resume requested by curr */ err = event.curr.is_abort_cb(NULL, event.curr.param, &resume_cb); - LL_ASSERT(err); + LL_ASSERT_DBG(err); if (err == -EAGAIN) { void *curr_param; @@ -954,9 +979,9 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, next = resume_enqueue(event.curr.is_abort_cb, event.curr.abort_cb, resume_cb, curr_param); - LL_ASSERT(next); + LL_ASSERT_ERR(next); } else { - LL_ASSERT(err == -ECANCELED); + LL_ASSERT_ERR(err == -ECANCELED); } } #endif /* CONFIG_BT_CTLR_LOW_LAT */ @@ -964,7 +989,7 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, return -EINPROGRESS; } - LL_ASSERT(!ready || &ready->prepare_param == prepare_param); + LL_ASSERT_ERR(!ready || &ready->prepare_param == prepare_param); event.curr.param = prepare_param->param; event.curr.is_abort_cb = is_abort_cb; @@ -996,8 +1021,8 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, /* Start the preempt timeout */ ret = preempt_ticker_start(next, NULL, next); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); #endif /* !CONFIG_BT_CTLR_LOW_LAT */ return err; @@ -1012,7 +1037,7 @@ static int init_reset(void) static inline void done_inc(void) { event.done.lll_count++; - LL_ASSERT(event.done.lll_count != event.done.ull_count); + LL_ASSERT_ERR(event.done.lll_count != event.done.ull_count); } #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */ @@ -1066,7 +1091,7 @@ static void ticker_stop_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(preempt_stop_req != preempt_stop_ack); + LL_ASSERT_ERR(preempt_stop_req != preempt_stop_ack); preempt_stop_ack = preempt_stop_req; /* We do not fail on status not being success because under scenarios @@ -1077,7 +1102,7 @@ static void ticker_stop_op_cb(uint32_t status, void *param) * safe to reset preempt_req and preempt_ack here. */ if (status == TICKER_STATUS_SUCCESS) { - LL_ASSERT(preempt_req != preempt_ack); + LL_ASSERT_ERR(preempt_req != preempt_ack); } preempt_req = preempt_ack; @@ -1086,18 +1111,18 @@ static void ticker_stop_op_cb(uint32_t status, void *param) static void ticker_start_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); /* Increase preempt requested count before acknowledging that the * ticker start operation for the preempt timeout has been handled. */ - LL_ASSERT(preempt_req == preempt_ack); + LL_ASSERT_ERR(preempt_req == preempt_ack); preempt_req++; /* Increase preempt start ack count, to acknowledge that the ticker * start operation has been handled. */ - LL_ASSERT(preempt_start_req != preempt_start_ack); + LL_ASSERT_ERR(preempt_start_req != preempt_start_ack); preempt_start_ack = preempt_start_req; } @@ -1141,8 +1166,8 @@ static uint32_t preempt_ticker_start(struct lll_event *first, /* Stop any scheduled preempt ticker */ ret = preempt_ticker_stop(); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); /* Schedule short preempt timeout */ first = next; @@ -1196,8 +1221,8 @@ static uint32_t preempt_ticker_stop(void) TICKER_USER_ID_LLL, TICKER_ID_LLL_PREEMPT, ticker_stop_op_cb, NULL); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); return ret; } @@ -1210,13 +1235,13 @@ static void preempt_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, static struct mayfly mfy = {0, 0, &link, NULL, preempt}; uint32_t ret; - LL_ASSERT(preempt_ack != preempt_req); + LL_ASSERT_ERR(preempt_ack != preempt_req); preempt_ack = preempt_req; mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void preempt(void *param) @@ -1287,8 +1312,8 @@ static void preempt(void *param) /* Start the preempt timeout for (short) ready event */ ret = preempt_ticker_start(ready, NULL, ready); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); return; } @@ -1322,7 +1347,7 @@ static void preempt(void *param) return; } - LL_ASSERT(ready->prepare_param.param == param); + LL_ASSERT_ERR(ready->prepare_param.param == param); } /* Check if current event want to continue */ @@ -1345,8 +1370,8 @@ static void preempt(void *param) /* Start the preempt timeout for next ready prepare */ ret = preempt_ticker_start(ready, NULL, ready); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } else { /* Let preemptor LLL know about the cancelled prepare */ @@ -1416,9 +1441,9 @@ static void preempt(void *param) /* Enqueue as resume event */ iter = resume_enqueue(is_abort_cb, abort_cb, resume_cb, curr_param); - LL_ASSERT(iter); + LL_ASSERT_ERR(iter); } else { - LL_ASSERT(err == -ECANCELED); + LL_ASSERT_ERR(err == -ECANCELED); } } #else /* CONFIG_BT_CTLR_LOW_LAT */ @@ -1432,8 +1457,8 @@ static void mfy_ticker_job_idle_get(void *param) ret = ticker_job_idle_get(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_LOW, ticker_op_job_disable, NULL); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } static void ticker_op_job_disable(uint32_t status, void *op_context) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c index 96d93b2b855b..8c7837bf9805 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c @@ -435,12 +435,12 @@ struct pdu_adv *lll_adv_pdu_alloc_pdu_adv(void) } err = k_sem_take(&sem_pdu_free, PDU_FREE_TIMEOUT); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); k_sem_reset(&sem_pdu_free); p = MFIFO_DEQUEUE(pdu_free); - LL_ASSERT(p); + LL_ASSERT_ERR(p); #if defined(CONFIG_BT_CTLR_ADV_PDU_LINK) PDU_ADV_NEXT_PTR(p) = NULL; @@ -681,10 +681,10 @@ void lll_adv_prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } bool lll_adv_scan_req_check(struct lll_adv *lll, struct pdu_adv *sr, @@ -836,7 +836,7 @@ static void *adv_extra_data_allocate(struct lll_adv_pdu *pdu, uint8_t last) extra_data = MFIFO_DEQUEUE_PEEK(extra_data_free); if (extra_data) { err = k_sem_take(&sem_extra_data_free, K_NO_WAIT); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); MFIFO_DEQUEUE(extra_data_free); pdu->extra_data[last] = extra_data; @@ -852,10 +852,10 @@ static void *adv_extra_data_allocate(struct lll_adv_pdu *pdu, uint8_t last) } err = k_sem_take(&sem_extra_data_free, PDU_FREE_TIMEOUT); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); extra_data = MFIFO_DEQUEUE(extra_data_free); - LL_ASSERT(extra_data); + LL_ASSERT_ERR(extra_data); pdu->extra_data[last] = (void *)extra_data; @@ -913,7 +913,7 @@ static void extra_data_free_sem_give(void) retval = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!retval); + LL_ASSERT_ERR(!retval); } #else /* !CONFIG_BT_CTLR_ZLI */ @@ -1062,7 +1062,7 @@ static int prepare_cb(struct lll_prepare_param *p) #endif ret = lll_prepare_done(lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_A(1); @@ -1102,7 +1102,7 @@ static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb) /* Retain HF clk */ err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); return -EAGAIN; #endif /* CONFIG_BT_PERIPHERAL */ @@ -1140,7 +1140,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); lll_done(param); } @@ -1178,11 +1178,16 @@ static void isr_tx(void *param) /* setup Rx buffer */ node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_pkt_rx_set(node_rx->pdu); /* assert if radio packet ptr is not set and radio started rx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -1421,7 +1426,7 @@ static void isr_done(void *param) struct event_done_extra *extra; extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_ADV); - LL_ASSERT(extra); + LL_ASSERT_ERR(extra); } #endif /* CONFIG_BT_CTLR_ADV_EXT || CONFIG_BT_CTLR_JIT_SCHEDULING */ @@ -1459,7 +1464,7 @@ static void isr_abort_all(void *param) /* Abort any LLL prepare/resume enqueued in pipeline */ mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_LLL, 1U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } #endif /* CONFIG_BT_PERIPHERAL */ @@ -1470,7 +1475,7 @@ static struct pdu_adv *chan_prepare(struct lll_adv *lll) uint8_t upd; chan = find_lsb_set(lll->chan_map_curr); - LL_ASSERT(chan); + LL_ASSERT_DBG(chan); lll->chan_map_curr &= (lll->chan_map_curr - 1); @@ -1479,7 +1484,7 @@ static struct pdu_adv *chan_prepare(struct lll_adv *lll) /* FIXME: get latest only when primary PDU without Aux PDUs */ upd = 0U; pdu = lll_adv_data_latest_get(lll, &upd); - LL_ASSERT(pdu); + LL_ASSERT_DBG(pdu); radio_pkt_tx_set(pdu); @@ -1489,7 +1494,7 @@ static struct pdu_adv *chan_prepare(struct lll_adv *lll) struct pdu_adv *scan_pdu; scan_pdu = lll_adv_scan_rsp_latest_get(lll, &upd); - LL_ASSERT(scan_pdu); + LL_ASSERT_DBG(scan_pdu); #if defined(CONFIG_BT_CTLR_PRIVACY) if (upd) { @@ -1546,7 +1551,7 @@ static inline int isr_rx_pdu(struct lll_adv *lll, #endif /* CONFIG_BT_CTLR_PRIVACY */ node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu_rx = (void *)node_rx->pdu; pdu_adv = lll_adv_data_curr_get(lll); @@ -1571,7 +1576,12 @@ static inline int isr_rx_pdu(struct lll_adv *lll, radio_pkt_tx_set(lll_adv_scan_rsp_curr_get(lll)); /* assert if radio packet ptr is not set and radio started tx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -1642,7 +1652,12 @@ static inline int isr_rx_pdu(struct lll_adv *lll, radio_disable(); /* assert if radio started tx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c index 731ca94ed508..f4b48cabab9c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c @@ -104,10 +104,10 @@ void lll_adv_aux_prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); err = lll_prepare(lll_is_abort_cb, lll_abort_cb, prepare_cb, 0, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } void lll_adv_aux_pback_prepare(void *param) @@ -143,7 +143,7 @@ static int prepare_cb(struct lll_prepare_param *p) /* FIXME: get latest only when primary PDU without Aux PDUs */ upd = 0U; sec_pdu = lll_adv_aux_data_latest_get(lll, &upd); - LL_ASSERT(sec_pdu); + LL_ASSERT_DBG(sec_pdu); #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) struct ll_adv_aux_set *aux; @@ -163,14 +163,14 @@ static int prepare_cb(struct lll_prepare_param *p) /* Get reference to primary PDU */ pri_pdu = lll_adv_data_curr_get(lll_adv); - LL_ASSERT(pri_pdu->type == PDU_ADV_TYPE_EXT_IND); + LL_ASSERT_DBG(pri_pdu->type == PDU_ADV_TYPE_EXT_IND); /* Get reference to common extended header */ com_hdr = (void *)&pri_pdu->adv_ext_ind; /* Get reference to aux pointer structure */ err = aux_ptr_get(pri_pdu, &aux_ptr); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); /* Abort if no aux_ptr filled */ if (unlikely(!aux_ptr || !PDU_ADV_AUX_PTR_OFFSET_GET(aux_ptr))) { @@ -218,7 +218,7 @@ static int prepare_cb(struct lll_prepare_param *p) struct pdu_adv *scan_pdu; scan_pdu = lll_adv_scan_rsp_latest_get(lll_adv, &upd); - LL_ASSERT(scan_pdu); + LL_ASSERT_DBG(scan_pdu); radio_isr_set(isr_tx_rx, lll); radio_tmr_tifs_set(EVENT_IFS_US); @@ -340,7 +340,7 @@ static int prepare_cb(struct lll_prepare_param *p) #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_BACK2BACK */ ret = lll_prepare_done(lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_A(1); @@ -411,7 +411,7 @@ static void isr_early_abort(void *param) /* Generate auxiliary radio event done */ extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_ADV_AUX); - LL_ASSERT(extra); + LL_ASSERT_ERR(extra); radio_isr_set(isr_race, param); if (!radio_is_idle()) { @@ -419,7 +419,7 @@ static void isr_early_abort(void *param) } err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); lll_done(NULL); } @@ -434,7 +434,7 @@ static void isr_done(void *param) /* Generate auxiliary radio event done */ extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_ADV_AUX); - LL_ASSERT(extra); + LL_ASSERT_ERR(extra); /* Cleanup radio event and dispatch the done event */ lll_isr_cleanup(param); @@ -462,14 +462,14 @@ static void isr_tx_chain(void *param) /* Get reference to aux pointer structure */ err = aux_ptr_get(lll_aux->last_pdu, &aux_ptr); - LL_ASSERT(!err && aux_ptr); + LL_ASSERT_ERR(!err && aux_ptr); /* Use channel idx that was in aux_ptr */ lll_chan_set(aux_ptr->chan_idx); /* Get reference to the auxiliary chain PDU */ pdu = lll_adv_pdu_linked_next_get(lll_aux->last_pdu); - LL_ASSERT(pdu); + LL_ASSERT_DBG(pdu); /* Set the last used auxiliary PDU for transmission */ lll_aux->last_pdu = pdu; @@ -488,7 +488,12 @@ static void isr_tx_chain(void *param) radio_pkt_tx_set(pdu); /* assert if radio packet ptr is not set and radio started rx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -552,7 +557,7 @@ static void aux_ptr_chan_idx_set(struct lll_adv_aux *lll, struct pdu_adv *pdu) /* Get reference to aux pointer structure */ err = aux_ptr_get(pdu, &aux_ptr); - LL_ASSERT(!err && aux_ptr); + LL_ASSERT_ERR(!err && aux_ptr); /* Calculate a new channel index */ aux = HDR_LLL2ULL(lll); @@ -598,11 +603,16 @@ static void isr_tx_rx(void *param) /* setup Rx buffer */ node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_pkt_rx_set(node_rx->pdu); /* assert if radio packet ptr is not set and radio started rx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -754,12 +764,12 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux, uint8_t phy_flags_rx, lll = lll_aux->adv; node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu_rx = (void *)node_rx->pdu; pdu_adv = lll_adv_data_curr_get(lll); pdu_aux = lll_adv_aux_data_latest_get(lll_aux, &upd); - LL_ASSERT(pdu_aux); + LL_ASSERT_DBG(pdu_aux); hdr = &pdu_aux->adv_ext_ind.ext_hdr; @@ -809,7 +819,12 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux, uint8_t phy_flags_rx, radio_pkt_tx_set(sr_pdu); /* assert if radio packet ptr is not set and radio started tx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -881,7 +896,12 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux, uint8_t phy_flags_rx, radio_pkt_tx_set(pdu_tx); /* assert if radio packet ptr is not set and radio started tx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c index 0b9ff8d938c2..cc26f729dfce 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c @@ -115,7 +115,7 @@ static void prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); p = param; @@ -135,7 +135,7 @@ static void create_prepare_bh(void *param) /* Invoke common pipeline handling of prepare */ err = lll_prepare(lll_is_abort_cb, lll_abort_cb, create_prepare_cb, 0U, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } static void prepare_bh(void *param) @@ -144,7 +144,7 @@ static void prepare_bh(void *param) /* Invoke common pipeline handling of prepare */ err = lll_prepare(lll_is_abort_cb, lll_abort_cb, prepare_cb, 0U, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } static int create_prepare_cb(struct lll_prepare_param *p) @@ -269,7 +269,7 @@ static int prepare_cb_common(struct lll_prepare_param *p) stream_handle = lll->stream_handle[bis_idx]; handle = LL_BIS_ADV_HANDLE_FROM_IDX(stream_handle); stream = ull_adv_iso_lll_stream_get(stream_handle); - LL_ASSERT(stream); + LL_ASSERT_DBG(stream); do { link = memq_peek(stream->memq_tx.head, @@ -448,7 +448,7 @@ static int prepare_cb_common(struct lll_prepare_param *p) #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */ ret = lll_prepare_done(lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); /* Calculate ahead the next subevent channel index */ if (false) { @@ -470,7 +470,7 @@ static int prepare_cb_common(struct lll_prepare_param *p) #endif /* CONFIG_BT_CTLR_ADV_ISO_INTERLEAVED */ } else { - LL_ASSERT(false); + LL_ASSERT_DBG(false); } return 0; @@ -582,7 +582,7 @@ static void isr_tx_common(void *param, } else { bis = 0U; - LL_ASSERT(false); + LL_ASSERT_DBG(false); } if (!is_ctrl) { @@ -649,7 +649,7 @@ static void isr_tx_common(void *param, stream_handle = lll->stream_handle[bis_idx]; handle = LL_BIS_ADV_HANDLE_FROM_IDX(stream_handle); stream = ull_adv_iso_lll_stream_get(stream_handle); - LL_ASSERT(stream); + LL_ASSERT_DBG(stream); do { struct node_tx_iso *tx; @@ -727,7 +727,7 @@ static void isr_tx_common(void *param, /* FIXME: memq_peek_n function does not support indices > UINT8_MAX, * add assertion check to honor this limitation. */ - LL_ASSERT(payload_index <= UINT8_MAX); + LL_ASSERT_DBG(payload_index <= UINT8_MAX); } else { payload_index = lll->bn_curr - 1U; /* 3 bits */ } @@ -742,7 +742,7 @@ static void isr_tx_common(void *param, stream_handle = lll->stream_handle[lll->bis_curr - 1U]; stream = ull_adv_iso_lll_stream_get(stream_handle); - LL_ASSERT(stream); + LL_ASSERT_DBG(stream); link = memq_peek_n(stream->memq_tx.head, stream->memq_tx.tail, payload_index, (void **)&tx); @@ -869,7 +869,12 @@ static void isr_tx_common(void *param, } /* assert if radio packet ptr is not set and radio started tx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -917,7 +922,7 @@ static void isr_tx_common(void *param, #endif /* CONFIG_BT_CTLR_ADV_ISO_INTERLEAVED */ } else { - LL_ASSERT(false); + LL_ASSERT_DBG(false); } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { @@ -1033,7 +1038,7 @@ static void isr_done_term(void *param) lll_isr_status_reset(); lll = param; - LL_ASSERT(lll->ctrl_expire); + LL_ASSERT_DBG(lll->ctrl_expire); elapsed_event = lll->latency_event + 1U; if (lll->ctrl_expire > elapsed_event) { @@ -1070,7 +1075,7 @@ static void isr_done_term(void *param) * Advertising PDU. */ rx = ull_pdu_rx_alloc(); - LL_ASSERT(rx); + LL_ASSERT_ERR(rx); rx->hdr.type = NODE_RX_TYPE_BIG_CHM_COMPLETE; rx->rx_ftr.param = lll; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c index e30b6d6b8d2a..be8b8aa03a41 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c @@ -86,11 +86,11 @@ void lll_adv_sync_prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Invoke common pipeline handling of prepare */ err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } static int init_reset(void) @@ -176,7 +176,7 @@ static int prepare_cb(struct lll_prepare_param *p) upd = 0U; pdu = lll_adv_sync_data_latest_get(lll, NULL, &upd); - LL_ASSERT(pdu); + LL_ASSERT_DBG(pdu); #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX) lll_df_cte_tx_enable(lll, pdu, &cte_len_us); @@ -278,7 +278,7 @@ static int prepare_cb(struct lll_prepare_param *p) #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */ ret = lll_prepare_done(lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_A(1); @@ -305,7 +305,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Accumulate the latency as event is aborted while being in pipeline */ lll = prepare_param->param; @@ -336,7 +336,7 @@ static void isr_done(void *param) * the thread context. */ rx = ull_pdu_rx_alloc(); - LL_ASSERT(rx); + LL_ASSERT_ERR(rx); rx->hdr.type = NODE_RX_TYPE_SYNC_CHM_COMPLETE; rx->rx_ftr.param = lll; @@ -370,14 +370,14 @@ static void isr_tx(void *param) /* Get reference to aux pointer structure */ err = aux_ptr_get(lll_sync->last_pdu, &aux_ptr); - LL_ASSERT(!err && aux_ptr); + LL_ASSERT_ERR(!err && aux_ptr); /* Use channel idx that was in aux_ptr */ lll_chan_set(aux_ptr->chan_idx); /* Get reference to the auxiliary chain PDU */ pdu = lll_adv_pdu_linked_next_get(lll_sync->last_pdu); - LL_ASSERT(pdu); + LL_ASSERT_DBG(pdu); /* Set the last used auxiliary PDU for transmission */ lll_sync->last_pdu = pdu; @@ -401,7 +401,12 @@ static void isr_tx(void *param) radio_pkt_tx_set(pdu); /* assert if radio packet ptr is not set and radio started rx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -509,7 +514,7 @@ static void aux_ptr_chan_idx_set(struct lll_adv_sync *lll, struct pdu_adv *pdu) /* Get reference to aux pointer structure */ err = aux_ptr_get(pdu, &aux_ptr); - LL_ASSERT(!err && aux_ptr); + LL_ASSERT_ERR(!err && aux_ptr); /* Calculate a new channel index */ chan_idx = lll_chan_sel_2(lll->data_chan_counter, lll->data_chan_id, diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c index 4f082b4957a4..fb170046a96f 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central.c @@ -72,12 +72,12 @@ void lll_central_prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Invoke common pipeline handling of prepare */ err = lll_prepare(lll_conn_central_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } static int init_reset(void) @@ -139,7 +139,7 @@ static int prepare_cb(struct lll_prepare_param *p) lll->data_chan_count); #else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */ data_chan_use = 0; - LL_ASSERT(0); + LL_ASSERT_DBG(0); #endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */ } else { data_chan_use = lll_chan_sel_1(&lll->data_chan_use, @@ -266,7 +266,7 @@ static int prepare_cb(struct lll_prepare_param *p) #endif /* !CONFIG_BT_CTLR_XTAL_ADVANCED */ ret = lll_prepare_done(lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_M(1); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index 7ae759dd2bec..3d02a092f33f 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -34,6 +34,7 @@ #include "lll_internal.h" #include "lll_tim_internal.h" +#include "lll_prof_internal.h" #include "ll_feat.h" @@ -96,11 +97,11 @@ void lll_central_iso_prepare(void *param) /* Initiate HF clock start up */ err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Invoke common pipeline handling of prepare */ err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0U, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } static int init_reset(void) @@ -142,7 +143,7 @@ static int prepare_cb(struct lll_prepare_param *p) cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle_curr); } while (cis_lll && !cis_lll->active); - LL_ASSERT(cis_lll); + LL_ASSERT_DBG(cis_lll); /* Unconditionally set the prepared flag. * This flag ensures current CIG event does not pick up a new CIS becoming active when the @@ -155,7 +156,7 @@ static int prepare_cb(struct lll_prepare_param *p) /* Get reference to ACL context */ conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); /* Pick the event_count calculated in the ULL prepare */ cis_lll->event_count = cis_lll->event_count_prepare; @@ -394,7 +395,7 @@ static int prepare_cb(struct lll_prepare_param *p) /* Prepare is done */ ret = lll_prepare_done(cig_lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_M(1); @@ -434,7 +435,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* Get reference to ACL context */ const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); if (conn_lll->enc_rx) { radio_ccm_disable(); @@ -448,7 +449,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Get reference to CIG LLL context */ cig_lll = prepare_param->param; @@ -466,6 +467,10 @@ static void isr_tx(void *param) struct node_rx_pdu *node_rx; uint32_t hcto; + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_latency_capture(); + } + /* Call to ensure packet/event timer accumulates the elapsed time * under single timer use. */ @@ -489,13 +494,13 @@ static void isr_tx(void *param) /* Acquire rx node for reception */ node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); #if defined(CONFIG_BT_CTLR_LE_ENC) /* Get reference to ACL context */ const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); #endif /* CONFIG_BT_CTLR_LE_ENC */ /* PHY */ @@ -538,7 +543,12 @@ static void isr_tx(void *param) } /* assert if radio packet ptr is not set and radio started rx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } /* +/- 2us active clock jitter, +1 us PPI to timer start compensation */ hcto = radio_tmr_tifs_base_get() + cis_lll->tifs_us + @@ -598,12 +608,12 @@ static void isr_tx(void *param) (cis_lll->sub_interval * se_curr); start_us = radio_tmr_start_us(1U, subevent_us); - LL_ASSERT(start_us == (subevent_us + 1U)); + LL_ASSERT_ERR(start_us == (subevent_us + 1U)); #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ /* Get reference to ACL context */ evt_conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(evt_conn_lll != NULL); + LL_ASSERT_DBG(evt_conn_lll != NULL); /* Calculate the radio channel to use for next subevent */ data_chan_id = lll_chan_id(cis_lll->access_addr); @@ -642,7 +652,7 @@ static void isr_tx(void *param) subevent_us += next_cis_lll->offset - cis_offset_first; start_us = radio_tmr_start_us(1U, subevent_us); - LL_ASSERT(start_us == (subevent_us + 1U)); + LL_ASSERT_ERR(start_us == (subevent_us + 1U)); #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ /* Event counter value, 0-15 bit of cisEventCounter */ @@ -650,7 +660,7 @@ static void isr_tx(void *param) /* Get reference to ACL context */ next_conn_lll = ull_conn_lll_get(next_cis_lll->acl_handle); - LL_ASSERT(next_conn_lll != NULL); + LL_ASSERT_DBG(next_conn_lll != NULL); /* Calculate the radio channel to use for ISO event */ data_chan_id = lll_chan_id(next_cis_lll->access_addr); @@ -705,6 +715,10 @@ static void isr_rx(void *param) uint8_t crc_ok; uint8_t cie; + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_latency_capture(); + } + /* Read radio status and events */ trx_done = radio_is_done(); if (trx_done) { @@ -758,7 +772,7 @@ static void isr_rx(void *param) /* Get reference to received PDU */ node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu_rx = (void *)node_rx->pdu; /* Tx ACK */ @@ -791,7 +805,7 @@ static void isr_rx(void *param) /* Get reference to ACL context */ const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); /* If required, wait for CCM to finish */ @@ -799,7 +813,7 @@ static void isr_rx(void *param) uint32_t done; done = radio_ccm_is_done(); - LL_ASSERT(done); + LL_ASSERT_ERR(done); if (!radio_ccm_mic_is_valid()) { /* Record MIC invalid */ @@ -880,7 +894,7 @@ static void isr_rx(void *param) /* Get reference to ACL context */ next_conn_lll = ull_conn_lll_get(next_cis_lll->acl_handle); - LL_ASSERT(next_conn_lll != NULL); + LL_ASSERT_DBG(next_conn_lll != NULL); /* Calculate CIS channel if not already calculated */ if (se_curr < cis_lll->nse) { @@ -898,7 +912,7 @@ static void isr_rx(void *param) subevent_us += next_cis_lll->offset - cis_offset_first; start_us = radio_tmr_start_us(1U, subevent_us); - LL_ASSERT(start_us == (subevent_us + 1U)); + LL_ASSERT_ERR(start_us == (subevent_us + 1U)); #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ /* Event counter value, 0-15 bit of cisEventCounter */ @@ -975,6 +989,10 @@ static void isr_rx(void *param) isr_prepare_subevent(param); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_send(); + } + return; isr_rx_done: @@ -1057,7 +1075,7 @@ static void isr_prepare_subevent(void *param) /* Get reference to ACL context */ const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); #endif /* CONFIG_BT_CTLR_LE_ENC */ /* PHY */ @@ -1116,7 +1134,7 @@ static void isr_prepare_subevent(void *param) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) start_us = radio_tmr_start_us(1U, subevent_us); - LL_ASSERT(start_us == (subevent_us + 1U)); + LL_ASSERT_ERR(start_us == (subevent_us + 1U)); #else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ /* Compensate for the 1 us added by radio_tmr_start_us() */ @@ -1131,6 +1149,13 @@ static void isr_prepare_subevent(void *param) radio_tmr_end_capture(); #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) + /* PA enable is overwriting packet end used in ISR profiling, hence + * back it up for later use. + */ + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_radio_end_backup(); + } + radio_gpio_pa_setup(); #if defined(CONFIG_BT_CTLR_PHY) @@ -1148,7 +1173,16 @@ static void isr_prepare_subevent(void *param) #endif /* !HAL_RADIO_GPIO_HAVE_PA_PIN */ /* assert if radio packet ptr is not set and radio started tx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } + + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_cputime_capture(); + } radio_isr_set(isr_tx, param); @@ -1169,7 +1203,7 @@ static void isr_done(void *param) payload_count_flush_or_inc_on_close(cis_lll); e = ull_event_done_extra_get(); - LL_ASSERT(e); + LL_ASSERT_ERR(e); e->type = EVENT_DONE_EXTRA_TYPE_CIS; e->trx_performed_bitmask = trx_performed_bitmask; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index 1527987c02d0..76663641f80a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -189,7 +189,7 @@ int lll_conn_central_is_abort_cb(void *next, void *curr, return -EBUSY; } - LL_ASSERT(trx_busy_iteration < CENTRAL_TRX_BUSY_ITERATION_MAX); + LL_ASSERT_DBG(trx_busy_iteration < CENTRAL_TRX_BUSY_ITERATION_MAX); return -ECANCELED; } @@ -223,7 +223,7 @@ int lll_conn_peripheral_is_abort_cb(void *next, void *curr, return -EBUSY; } - LL_ASSERT(trx_busy_iteration < PERIPHERAL_TRX_BUSY_ITERATION_MAX); + LL_ASSERT_DBG(trx_busy_iteration < PERIPHERAL_TRX_BUSY_ITERATION_MAX); return -ECANCELED; } @@ -268,7 +268,7 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Get reference to LLL connection context */ lll = prepare_param->param; @@ -290,7 +290,7 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param) /* Extra done event, to check supervision timeout */ e = ull_event_done_extra_get(); - LL_ASSERT(e); + LL_ASSERT_ERR(e); e->type = EVENT_DONE_EXTRA_TYPE_CONN; e->trx_cnt = 0U; @@ -311,9 +311,6 @@ void lll_conn_isr_rx(void *param) struct pdu_data *pdu_data_tx; struct node_rx_pdu *node_rx; struct node_tx *tx_release; -#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) - uint32_t pa_lna_enable_us; -#endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */ uint8_t is_rx_enqueue; struct lll_conn *lll; uint8_t rssi_ready; @@ -367,7 +364,7 @@ void lll_conn_isr_rx(void *param) lll = param; node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu_data_rx = (void *)node_rx->pdu; @@ -384,7 +381,12 @@ void lll_conn_isr_rx(void *param) radio_disable(); /* assert if radio started tx before being disabled */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", + __func__, lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } goto lll_conn_isr_rx_exit; } @@ -468,10 +470,13 @@ void lll_conn_isr_rx(void *param) } else if (!lll->role) { radio_disable(); - /* assert if radio packet ptr is not set and radio - * started tx. - */ - LL_ASSERT(!radio_is_ready()); + /* assert if radio started tx before being disabled */ + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", + __func__, lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } /* Restore state if last transmitted was empty PDU */ lll->empty = is_empty_pdu_tx_retry; @@ -507,6 +512,7 @@ void lll_conn_isr_rx(void *param) lll_conn_tx_pkt_set(lll, pdu_data_tx); #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) + uint32_t pa_lna_enable_us; #if defined(CONFIG_BT_CTLR_PROFILE_ISR) /* PA enable is overwriting packet end used in ISR profiling, hence @@ -529,10 +535,10 @@ void lll_conn_isr_rx(void *param) /* assert if radio packet ptr is not set and radio started tx */ if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { - LL_ASSERT_MSG(!radio_is_address(), "%s: Radio ISR latency: %u", __func__, + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, lll_prof_latency_get()); } else { - LL_ASSERT(!radio_is_address()); + LL_ASSERT_ERR(!radio_is_ready()); } #if defined(CONFIG_BT_CTLR_TX_DEFER) @@ -564,7 +570,7 @@ void lll_conn_isr_rx(void *param) is_ull_rx = 0U; if (tx_release) { - LL_ASSERT(lll->handle != 0xFFFF); + LL_ASSERT_DBG(lll->handle != 0xFFFF); ull_conn_lll_ack_enqueue(lll->handle, tx_release); @@ -727,15 +733,15 @@ void lll_conn_isr_tx(void *param) /* assert if radio packet ptr is not set and radio started rx */ if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { - LL_ASSERT_MSG(!radio_is_address(), "%s: Radio ISR latency: %u", __func__, + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, lll_prof_latency_get()); } else { - LL_ASSERT(!radio_is_address()); + LL_ASSERT_ERR(!radio_is_ready()); } #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) pdu_tx = get_last_tx_pdu(lll); - LL_ASSERT(pdu_tx); + LL_ASSERT_DBG(pdu_tx); if (pdu_tx->cp) { cte_len = CTE_LEN_US(pdu_tx->octet3.cte_info.time); @@ -830,7 +836,7 @@ void lll_conn_rx_pkt_set(struct lll_conn *lll) uint8_t phy; node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); /* In case of ISR latencies, if packet pointer has not been set on time * then we do not want to check uninitialized length in rx buffer that @@ -1035,7 +1041,7 @@ static void isr_done(void *param) lll_isr_status_reset(); e = ull_event_done_extra_get(); - LL_ASSERT(e); + LL_ASSERT_ERR(e); e->type = EVENT_DONE_EXTRA_TYPE_CONN; e->trx_cnt = trx_cnt; @@ -1176,7 +1182,7 @@ static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx, FORCE_MD_CNT_SET(); } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } if (IS_ENABLED(CONFIG_BT_CENTRAL) && !lll->role && @@ -1203,7 +1209,7 @@ static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx, uint32_t done; done = radio_ccm_is_done(); - LL_ASSERT(done); + LL_ASSERT_ERR(done); bool mic_failure = !radio_ccm_mic_is_valid(); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c index f4a12ef5e934..a9a575a32306 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_df.c @@ -103,7 +103,7 @@ void lll_df_cte_tx_enable(struct lll_adv_sync *lll_sync, const struct pdu_adv *p const struct lll_df_adv_cfg *df_cfg; df_cfg = lll_adv_sync_extra_data_curr_get(lll_sync); - LL_ASSERT(df_cfg); + LL_ASSERT_DBG(df_cfg); lll_df_cte_tx_configure(df_cfg->cte_type, df_cfg->cte_length, df_cfg->ant_sw_len, df_cfg->ant_ids); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c index 8c3b83efd721..a25265400db8 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c @@ -73,7 +73,7 @@ void lll_periph_prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); p = param; @@ -82,7 +82,7 @@ void lll_periph_prepare(void *param) /* Invoke common pipeline handling of prepare */ err = lll_prepare(lll_conn_peripheral_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0U, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } static int init_reset(void) @@ -143,7 +143,7 @@ static int prepare_cb(struct lll_prepare_param *p) lll->data_chan_count); #else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */ data_chan_use = 0; - LL_ASSERT(0); + LL_ASSERT_DBG(0); #endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */ } else { data_chan_use = lll_chan_sel_1(&lll->data_chan_use, @@ -355,7 +355,7 @@ static int prepare_cb(struct lll_prepare_param *p) #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */ ret = lll_prepare_done(lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_S(1); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index 5d23a12993bd..8178be1c7d26 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -34,6 +34,7 @@ #include "lll_internal.h" #include "lll_tim_internal.h" +#include "lll_prof_internal.h" #include "ll_feat.h" @@ -99,7 +100,7 @@ void lll_peripheral_iso_prepare(void *param) /* Initiate HF clock start up */ err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); p = param; @@ -107,7 +108,7 @@ void lll_peripheral_iso_prepare(void *param) /* Invoke common pipeline handling of prepare */ err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0U, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } void lll_peripheral_iso_flush(uint16_t handle, struct lll_conn_iso_stream *lll) @@ -156,7 +157,7 @@ static int prepare_cb(struct lll_prepare_param *p) cis_lll = ull_conn_iso_lll_stream_sorted_get_by_group(cig_lll, &cis_handle_curr); } while (cis_lll && !cis_lll->active); - LL_ASSERT(cis_lll); + LL_ASSERT_DBG(cis_lll); /* Unconditionally set the prepared flag. * This flag ensures current CIG event does not pick up a new CIS becoming active when the @@ -169,7 +170,7 @@ static int prepare_cb(struct lll_prepare_param *p) /* Get reference to ACL context */ conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); /* Pick the event_count calculated in the ULL prepare */ cis_lll->event_count = cis_lll->event_count_prepare; @@ -232,7 +233,7 @@ static int prepare_cb(struct lll_prepare_param *p) lll_chan_set(data_chan_use); node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); /* Encryption */ if (false) { @@ -409,7 +410,7 @@ static int prepare_cb(struct lll_prepare_param *p) /* Prepare is done */ ret = lll_prepare_done(cig_lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_S(1); @@ -450,7 +451,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* Get reference to ACL context */ const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); if (conn_lll->enc_rx) { radio_ccm_disable(); @@ -464,7 +465,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Get reference to CIG LLL context */ cig_lll = prepare_param->param; @@ -496,6 +497,10 @@ static void isr_rx(void *param) uint8_t crc_ok; uint8_t cie; + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_latency_capture(); + } + /* Read radio status and events */ trx_done = radio_is_done(); if (trx_done) { @@ -573,7 +578,7 @@ static void isr_rx(void *param) /* Get reference to ACL context */ conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); if (crc_ok) { struct node_rx_pdu *node_rx; @@ -581,7 +586,7 @@ static void isr_rx(void *param) /* Get reference to received PDU */ node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu_rx = (void *)node_rx->pdu; @@ -619,7 +624,7 @@ static void isr_rx(void *param) uint32_t done; done = radio_ccm_is_done(); - LL_ASSERT(done); + LL_ASSERT_ERR(done); if (!radio_ccm_mic_is_valid()) { /* Record MIC invalid */ @@ -774,6 +779,13 @@ static void isr_rx(void *param) #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) uint32_t pa_lna_enable_us; + /* PA enable is overwriting packet end used in ISR profiling, hence + * back it up for later use. + */ + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_radio_end_backup(); + } + radio_gpio_pa_setup(); pa_lna_enable_us = radio_tmr_tifs_base_get() + cis_lll->tifs_us - @@ -788,7 +800,16 @@ static void isr_rx(void *param) #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */ /* assert if radio packet ptr is not set and radio started tx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } + + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_cputime_capture(); + } /* Schedule next subevent */ if (!cie && (se_curr < cis_lll->nse)) { @@ -863,8 +884,12 @@ static void isr_rx(void *param) #endif /* !CONFIG_BT_CTLR_PHY */ start_us = radio_tmr_start_us(0U, subevent_us); - LL_ASSERT(start_us == (subevent_us + 1U)); + LL_ASSERT_ERR(start_us == (subevent_us + 1U)); #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ + + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_send(); + } } static void isr_tx(void *param) @@ -876,6 +901,10 @@ static void isr_tx(void *param) uint32_t start_us; uint32_t hcto; + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + lll_prof_latency_capture(); + } + /* Call to ensure packet/event timer accumulates the elapsed time * under single timer use. */ @@ -887,13 +916,13 @@ static void isr_tx(void *param) cis_lll = param; node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); #if defined(CONFIG_BT_CTLR_LE_ENC) /* Get reference to ACL context */ const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); #endif /* CONFIG_BT_CTLR_LE_ENC */ /* PHY */ @@ -970,7 +999,7 @@ static void isr_tx(void *param) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) start_us = radio_tmr_start_us(0U, subevent_us); - LL_ASSERT(start_us == (subevent_us + 1U)); + LL_ASSERT_ERR(start_us == (subevent_us + 1U)); #else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ /* Compensate for the 1 us added by radio_tmr_start_us() */ @@ -994,6 +1023,10 @@ static void isr_tx(void *param) radio_tmr_hcto_configure_abs(hcto); +#if defined(CONFIG_BT_CTLR_PROFILE_ISR) || defined(HAL_RADIO_GPIO_HAVE_PA_PIN) + radio_tmr_end_capture(); +#endif /* CONFIG_BT_CTLR_PROFILE_ISR || HAL_RADIO_GPIO_HAVE_PA_PIN */ + #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) radio_gpio_lna_setup(); @@ -1058,7 +1091,7 @@ static void isr_prepare_subevent(void *param) /* Get reference to ACL context */ conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); /* Calculate the radio channel to use for next subevent */ @@ -1084,7 +1117,7 @@ static void isr_prepare_subevent_next_cis(void *param) /* Get reference to ACL context */ conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); /* Event counter value, 0-15 bit of cisEventCounter */ event_counter = cis_lll->event_count; @@ -1116,13 +1149,13 @@ static void isr_prepare_subevent_common(void *param) cis_lll = param; node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); #if defined(CONFIG_BT_CTLR_LE_ENC) /* Get reference to ACL context */ const struct lll_conn *conn_lll = ull_conn_lll_get(cis_lll->acl_handle); - LL_ASSERT(conn_lll != NULL); + LL_ASSERT_DBG(conn_lll != NULL); #endif /* CONFIG_BT_CTLR_LE_ENC */ /* PHY */ @@ -1203,7 +1236,7 @@ static void isr_prepare_subevent_common(void *param) } start_us = radio_tmr_start_us(0U, subevent_us); - LL_ASSERT(!trx_performed_bitmask || (start_us == (subevent_us + 1U))); + LL_ASSERT_ERR(!trx_performed_bitmask || (start_us == (subevent_us + 1U))); /* If no anchor point sync yet, continue to capture access address * timestamp. @@ -1264,7 +1297,7 @@ static void isr_done(void *param) payload_count_rx_flush_or_txrx_inc(cis_lll); e = ull_event_done_extra_get(); - LL_ASSERT(e); + LL_ASSERT_ERR(e); e->type = EVENT_DONE_EXTRA_TYPE_CIS; e->trx_performed_bitmask = trx_performed_bitmask; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c index 79f60677be7c..5cfa63b3bcf5 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c @@ -125,10 +125,10 @@ void lll_scan_prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } void lll_scan_isr_resume(void *param) @@ -391,7 +391,7 @@ static int common_prepare_cb(struct lll_prepare_param *p, bool is_resume) #endif /* !CONFIG_BT_CTLR_ADV_EXT */ node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_pkt_rx_set(node_rx->pdu); @@ -497,8 +497,8 @@ static int common_prepare_cb(struct lll_prepare_param *p, bool is_resume) ticks_at_event, lll->ticks_window, TICKER_NULL_PERIOD, TICKER_NULL_REMAINDER, TICKER_NULL_LAZY, TICKER_NULL_SLOT, ticker_stop_cb, lll, ticker_op_start_cb, (void *)__LINE__); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } #if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_SCHED_ADVANCED) @@ -509,18 +509,24 @@ static int common_prepare_cb(struct lll_prepare_param *p, bool is_resume) static memq_link_t link; static struct mayfly mfy_after_cen_offset_get = { 0U, 0U, &link, NULL, ull_sched_mfy_after_cen_offset_get}; - uint32_t retval; + struct lll_prepare_param *prepare_param; - mfy_after_cen_offset_get.param = p; + /* Copy the required values to calculate the offsets */ + prepare_param = &lll->prepare_param; + prepare_param->ticks_at_expire = p->ticks_at_expire; + prepare_param->remainder = p->remainder; + prepare_param->param = lll; - retval = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_LOW, 1U, - &mfy_after_cen_offset_get); - LL_ASSERT(!retval); + mfy_after_cen_offset_get.param = prepare_param; + + ret = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_LOW, 1U, + &mfy_after_cen_offset_get); + LL_ASSERT_ERR(!ret); } #endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_SCHED_ADVANCED */ ret = lll_prepare_done(lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_O(1); @@ -561,7 +567,7 @@ static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb) /* Retain HF clock */ err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Yield to the pre-emptor, but be * resumed thereafter. @@ -629,7 +635,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); lll_done(param); } @@ -645,14 +651,14 @@ static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void ticker_op_start_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); } static void isr_rx(void *param) @@ -708,7 +714,7 @@ static void isr_rx(void *param) } node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu = (void *)node_rx->pdu; @@ -787,15 +793,15 @@ static void isr_tx(void *param) radio_switch_complete_and_disable(); node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_pkt_rx_set(node_rx->pdu); /* assert if radio packet ptr is not set and radio started rx */ if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { - LL_ASSERT_MSG(!radio_is_address(), "%s: Radio ISR latency: %u", __func__, + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, lll_prof_latency_get()); } else { - LL_ASSERT(!radio_is_address()); + LL_ASSERT_ERR(!radio_is_ready()); } #if defined(CONFIG_BT_CTLR_PRIVACY) @@ -865,7 +871,7 @@ static void isr_common_done(void *param) } node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_pkt_rx_set(node_rx->pdu); #if defined(CONFIG_BT_CTLR_PRIVACY) @@ -1006,7 +1012,7 @@ static void isr_abort(void *param) * detected in ULL. */ extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN); - LL_ASSERT(extra); + LL_ASSERT_ERR(extra); #endif /* CONFIG_BT_CTLR_ADV_EXT */ lll_isr_cleanup(param); @@ -1084,7 +1090,7 @@ static void isr_done_cleanup(void *param) * detected in ULL. */ extra = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN); - LL_ASSERT(extra); + LL_ASSERT_ERR(extra); } /* Prevent scan events in pipeline from being scheduled if duration has @@ -1103,7 +1109,7 @@ static void isr_done_cleanup(void *param) lll->is_aux_sched = 0U; node_rx2 = ull_pdu_rx_alloc(); - LL_ASSERT(node_rx2); + LL_ASSERT_ERR(node_rx2); node_rx2->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; @@ -1126,7 +1132,7 @@ static void isr_done_cleanup(void *param) mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_LLL, 1U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } lll_isr_cleanup(param); @@ -1217,10 +1223,10 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx, /* assert if radio packet ptr is not set and radio started tx */ if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { - LL_ASSERT_MSG(!radio_is_address(), "%s: Radio ISR latency: %u", __func__, + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, lll_prof_latency_get()); } else { - LL_ASSERT(!radio_is_address()); + LL_ASSERT_ERR(!radio_is_ready()); } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { @@ -1354,10 +1360,10 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx, /* assert if radio packet ptr is not set and radio started tx */ if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { - LL_ASSERT_MSG(!radio_is_address(), "%s: Radio ISR latency: %u", __func__, + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, lll_prof_latency_get()); } else { - LL_ASSERT(!radio_is_address()); + LL_ASSERT_ERR(!radio_is_ready()); } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { @@ -1567,7 +1573,7 @@ static int isr_rx_scan_report(struct lll_scan *lll, uint8_t devmatch_ok, break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c index 1a8aeb536f0c..8606a7913609 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c @@ -108,10 +108,10 @@ void lll_scan_aux_prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } uint8_t lll_scan_aux_setup(struct pdu_adv *pdu, uint8_t pdu_phy, @@ -132,7 +132,7 @@ uint8_t lll_scan_aux_setup(struct pdu_adv *pdu, uint8_t pdu_phy, uint32_t pdu_us; uint8_t phy; - LL_ASSERT(pdu->type == PDU_ADV_TYPE_EXT_IND); + LL_ASSERT_DBG(pdu->type == PDU_ADV_TYPE_EXT_IND); /* Get reference to extended header */ pri_com_hdr = (void *)&pdu->adv_ext_ind; @@ -231,7 +231,7 @@ uint8_t lll_scan_aux_setup(struct pdu_adv *pdu, uint8_t pdu_phy, } node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); /* Store the lll context, aux_ptr and start of PDU in footer */ ftr = &(node_rx->rx_ftr); @@ -499,7 +499,7 @@ static int prepare_cb(struct lll_prepare_param *p) RADIO_PKT_CONF_PHY(lll_aux->phy)); node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_pkt_rx_set(node_rx->pdu); @@ -607,21 +607,28 @@ static int prepare_cb(struct lll_prepare_param *p) static memq_link_t link; static struct mayfly mfy_after_cen_offset_get = { 0U, 0U, &link, NULL, ull_sched_mfy_after_cen_offset_get}; + struct lll_prepare_param *prepare_param; - /* NOTE: LLL scan instance passed, as done when + /* Copy the required values to calculate the offsets + * + * NOTE: LLL scan instance passed, as done when * establishing legacy connections. */ - p->param = lll; - mfy_after_cen_offset_get.param = p; + prepare_param = &lll->prepare_param; + prepare_param->ticks_at_expire = p->ticks_at_expire; + prepare_param->remainder = p->remainder; + prepare_param->param = lll; + + mfy_after_cen_offset_get.param = prepare_param; ret = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_LOW, 1U, &mfy_after_cen_offset_get); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } #endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_SCHED_ADVANCED */ ret = lll_prepare_done(lll_aux); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_O(1); @@ -640,7 +647,7 @@ static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb) /* Auxiliary event shall not overlap as they are not periodically * scheduled. */ - LL_ASSERT(next != curr); + LL_ASSERT_DBG(next != curr); lll = ull_scan_lll_is_valid_get(next); if (lll) { @@ -674,10 +681,10 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); e = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN_AUX); - LL_ASSERT(e); + LL_ASSERT_ERR(e); #if defined(CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS) e->lll = param; @@ -711,7 +718,7 @@ static void isr_done(void *param) * generated thereafter by HCI as incomplete. */ node_rx = ull_pdu_rx_alloc(); - LL_ASSERT(node_rx); + LL_ASSERT_ERR(node_rx); node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; @@ -725,7 +732,7 @@ static void isr_done(void *param) struct event_done_extra *e; e = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN_AUX); - LL_ASSERT(e); + LL_ASSERT_ERR(e); #if defined(CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS) e->lll = param; @@ -744,7 +751,7 @@ static void isr_done(void *param) mfy.param = scan_lll; ret = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_LLL, 1U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } lll_isr_cleanup(param); @@ -905,7 +912,7 @@ static void isr_rx(struct lll_scan *lll, struct lll_scan_aux *lll_aux, struct node_rx_pdu *node_rx2; node_rx2 = ull_pdu_rx_alloc(); - LL_ASSERT(node_rx2); + LL_ASSERT_ERR(node_rx2); node_rx2->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; @@ -1051,7 +1058,12 @@ static int isr_rx_pdu(struct lll_scan *lll, struct lll_scan_aux *lll_aux, radio_pkt_tx_set(pdu_tx); /* assert if radio packet ptr is not set and radio started tx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -1201,7 +1213,12 @@ static int isr_rx_pdu(struct lll_scan *lll, struct lll_scan_aux *lll_aux, radio_pkt_tx_set(pdu_tx); /* assert if radio packet ptr is not set and radio started tx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -1407,7 +1424,12 @@ static void isr_tx(struct lll_scan_aux *lll_aux, void *pdu_rx, radio_pkt_rx_set(pdu_rx); /* assert if radio packet ptr is not set and radio started rx */ - LL_ASSERT(!radio_is_ready()); + if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { + LL_ASSERT_MSG(!radio_is_ready(), "%s: Radio ISR latency: %u", __func__, + lll_prof_latency_get()); + } else { + LL_ASSERT_ERR(!radio_is_ready()); + } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { lll_prof_cputime_capture(); @@ -1469,7 +1491,7 @@ static void isr_tx_scan_req_ull_schedule(void *param) struct node_rx_pdu *node_rx; node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); isr_tx(param, node_rx->pdu, isr_rx_ull_schedule, param); } @@ -1483,7 +1505,7 @@ static void isr_tx_scan_req_lll_schedule(void *param) lll = node_rx_adv->rx_ftr.param; node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); isr_tx(lll->lll_aux, node_rx->pdu, isr_rx_lll_schedule, param); } @@ -1494,7 +1516,7 @@ static void isr_tx_connect_req(void *param) struct node_rx_pdu *node_rx; node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); isr_tx(param, (void *)node_rx->pdu, isr_rx_connect_rsp, param); } @@ -1544,7 +1566,7 @@ static void isr_rx_connect_rsp(void *param) * release it if failed to receive AUX_CONNECT_RSP PDU. */ rx = lll_aux->node_conn_rx; - LL_ASSERT(rx); + LL_ASSERT_DBG(rx); lll_aux->node_conn_rx = NULL; #if defined(CONFIG_BT_CTLR_PRIVACY) @@ -1562,7 +1584,7 @@ static void isr_rx_connect_rsp(void *param) pdu_tx = radio_pkt_scratch_get(); node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu_rx = (void *)node_rx->pdu; trx_done = isr_rx_connect_rsp_check(lll, pdu_tx, pdu_rx, @@ -1645,7 +1667,7 @@ static void isr_rx_connect_rsp(void *param) /* Send message to flush Auxiliary PDU list */ node_rx = ull_pdu_rx_alloc(); - LL_ASSERT(node_rx); + LL_ASSERT_ERR(node_rx); node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; @@ -1698,7 +1720,7 @@ static void isr_early_abort(void *param) struct event_done_extra *e; e = ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_SCAN_AUX); - LL_ASSERT(e); + LL_ASSERT_ERR(e); #if defined(CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS) e->lll = param; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index d549d914f591..fe5b9efdb989 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -101,11 +101,11 @@ void lll_sync_create_prepare(void *param) /* Request to start HF Clock */ err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Invoke common pipeline handling of prepare */ err = lll_prepare(is_abort_cb, abort_cb, create_prepare_cb, 0, param); - LL_ASSERT(!err || err == -EINPROGRESS); + LL_ASSERT_ERR(!err || err == -EINPROGRESS); } void lll_sync_prepare(void *param) @@ -114,11 +114,11 @@ void lll_sync_prepare(void *param) /* Request to start HF Clock */ err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Invoke common pipeline handling of prepare */ err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, param); - LL_ASSERT(err == 0 || err == -EINPROGRESS); + LL_ASSERT_ERR(err == 0 || err == -EINPROGRESS); } void lll_sync_aux_prepare_cb(struct lll_sync *lll, @@ -137,7 +137,7 @@ void lll_sync_aux_prepare_cb(struct lll_sync *lll, RADIO_PKT_CONF_PHY(lll_aux->phy)); node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_pkt_rx_set(node_rx->pdu); @@ -456,7 +456,7 @@ static int prepare_cb_common(struct lll_prepare_param *p, uint8_t chan_idx) lll_chan_set(chan_idx); node_rx = ull_pdu_rx_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_pkt_rx_set(node_rx->pdu); @@ -510,7 +510,7 @@ static int prepare_cb_common(struct lll_prepare_param *p, uint8_t chan_idx) #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */ ret = lll_prepare_done(lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_START_O(1); @@ -617,7 +617,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Get reference to LLL connection context */ lll = prepare_param->param; @@ -635,7 +635,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* Extra done event, to check sync lost */ e = ull_event_done_extra_get(); - LL_ASSERT(e); + LL_ASSERT_ERR(e); e->type = EVENT_DONE_EXTRA_TYPE_SYNC; e->trx_cnt = 0U; @@ -745,7 +745,7 @@ static void isr_aux_setup(void *param) aux_start_us -= EVENT_JITTER_US; start_us = radio_tmr_start_us(0, aux_start_us); - LL_ASSERT(start_us == (aux_start_us + 1U)); + LL_ASSERT_ERR(start_us == (aux_start_us + 1U)); /* Setup header complete timeout */ hcto = start_us; @@ -951,7 +951,7 @@ static void isr_rx_adv_sync_estab(void *param) /* TODO: Combine the early exit with above if-then-else block */ #if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) - LL_ASSERT(!lll->node_cte_incomplete); + LL_ASSERT_DBG(!lll->node_cte_incomplete); #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ goto isr_rx_done; @@ -1137,7 +1137,7 @@ static void isr_rx_aux_chain(void *param) * generated thereafter by HCI as incomplete. */ node_rx = ull_pdu_rx_alloc(); - LL_ASSERT(node_rx); + LL_ASSERT_ERR(node_rx); node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; @@ -1188,7 +1188,7 @@ static void isr_rx_done_cleanup(struct lll_sync *lll, uint8_t crc_ok, bool sync_ /* Calculate and place the drift information in done event */ e = ull_event_done_extra_get(); - LL_ASSERT(e); + LL_ASSERT_ERR(e); e->type = EVENT_DONE_EXTRA_TYPE_SYNC; e->trx_cnt = trx_cnt; @@ -1240,7 +1240,7 @@ static void isr_done(void *param) * generated thereafter by HCI as incomplete. */ node_rx = ull_pdu_rx_alloc(); - LL_ASSERT(node_rx); + LL_ASSERT_ERR(node_rx); node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE; @@ -1325,7 +1325,7 @@ static int iq_report_create_put(struct lll_sync *lll, uint8_t rssi_ready, uint8_ if (!lll->is_cte_incomplete && is_max_cte_reached(cfg->max_cte_count, cfg->cte_count)) { iq_report = ull_df_iq_report_alloc(); - LL_ASSERT(iq_report); + LL_ASSERT_ERR(iq_report); iq_report_create(lll, rssi_ready, packet_status, cfg->slot_durations, iq_report); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c index 4f4dad90754f..d6931c9b7f59 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c @@ -101,11 +101,11 @@ void lll_sync_iso_create_prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); err = lll_prepare(is_abort_cb, abort_cb, create_prepare_cb, 0U, param); - LL_ASSERT(err == 0 || err == -EINPROGRESS); + LL_ASSERT_ERR(err == 0 || err == -EINPROGRESS); } void lll_sync_iso_prepare(void *param) @@ -113,10 +113,10 @@ void lll_sync_iso_prepare(void *param) int err; err = lll_hfclock_on(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0U, param); - LL_ASSERT(err == 0 || err == -EINPROGRESS); + LL_ASSERT_ERR(err == 0 || err == -EINPROGRESS); } void lll_sync_iso_flush(uint8_t handle, struct lll_sync_iso *lll) @@ -288,7 +288,7 @@ static int prepare_cb_common(struct lll_prepare_param *p) #endif /* CONFIG_BT_CTLR_SYNC_ISO_INTERLEAVED */ } else { - LL_ASSERT(false); + LL_ASSERT_DBG(false); } } @@ -313,7 +313,7 @@ static int prepare_cb_common(struct lll_prepare_param *p) * setting up radio for new PDU reception. */ node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); /* Encryption */ if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && @@ -400,7 +400,7 @@ static int prepare_cb_common(struct lll_prepare_param *p) #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */ ret = lll_prepare_done(lll); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); /* Calculate ahead the next subevent channel index */ if (false) { @@ -422,7 +422,7 @@ static int prepare_cb_common(struct lll_prepare_param *p) #endif /* CONFIG_BT_CTLR_SYNC_ISO_INTERLEAVED */ } else { - LL_ASSERT(false); + LL_ASSERT_DBG(false); } return 0; @@ -468,7 +468,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) * currently in preparation pipeline. */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Get reference to LLL connection context */ lll = prepare_param->param; @@ -486,7 +486,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* Extra done event, to check sync lost */ e = ull_event_done_extra_get(); - LL_ASSERT(e); + LL_ASSERT_ERR(e); e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO; e->estab_failed = 0U; @@ -531,7 +531,7 @@ static void isr_rx_estab(void *param) * for new PDU reception. */ node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); /* Get reference to received PDU and validate MIC for non-empty PDU */ pdu = (void *)node_rx->pdu; @@ -540,7 +540,7 @@ static void isr_rx_estab(void *param) uint32_t done; done = radio_ccm_is_done(); - LL_ASSERT(done); + LL_ASSERT_ERR(done); mic_failure = !radio_ccm_mic_is_valid(); if (mic_failure) { @@ -555,7 +555,7 @@ static void isr_rx_estab(void *param) /* Calculate and place the drift information in done event */ e = ull_event_done_extra_get(); - LL_ASSERT(e); + LL_ASSERT_ERR(e); e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO_ESTAB; e->estab_failed = lll->term_reason ? 1U : 0U; @@ -659,7 +659,7 @@ static void isr_rx(void *param) } else { se_offset_us = 0U; - LL_ASSERT(false); + LL_ASSERT_DBG(false); } radio_tmr_aa_save(radio_tmr_aa_get() - se_offset_us); @@ -702,7 +702,7 @@ static void isr_rx(void *param) } node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu = (void *)node_rx->pdu; @@ -753,7 +753,7 @@ static void isr_rx(void *param) uint32_t done; done = radio_ccm_is_done(); - LL_ASSERT(done); + LL_ASSERT_ERR(done); mic_failure = !radio_ccm_mic_is_valid(); if (mic_failure) { @@ -850,7 +850,7 @@ static void isr_rx(void *param) * skip subevents as buffers at these high offset are unavailable. */ payload_offset = (lll->latency_event * lll->bn); - LL_ASSERT(payload_offset <= UINT8_MAX); + LL_ASSERT_ERR(payload_offset <= UINT8_MAX); /* Find the index of the (irc_curr)th bn = 1 Rx PDU * buffer. @@ -941,7 +941,7 @@ static void isr_rx(void *param) * these high offsets are unavailable. */ payload_offset = (lll->latency_event * lll->bn); - LL_ASSERT(payload_offset <= UINT8_MAX); + LL_ASSERT_ERR(payload_offset <= UINT8_MAX); /* Find the index of the (irc_curr)th bn = 1 Rx * PDU buffer. @@ -1062,7 +1062,7 @@ static void isr_rx(void *param) lll->bis_curr = sync_stream->bis_index; bis_idx = lll->bis_curr - 1U; } else { - LL_ASSERT(false); + LL_ASSERT_DBG(false); } } @@ -1261,7 +1261,7 @@ static void isr_rx(void *param) * available for setting up radio for new PDU reception. */ node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu = (void *)node_rx->pdu; } else { @@ -1288,7 +1288,7 @@ static void isr_rx(void *param) * available for setting up radio for new PDU reception. */ node_rx = ull_iso_pdu_rx_alloc_peek(1U); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); pdu = (void *)node_rx->pdu; } else { @@ -1331,7 +1331,7 @@ static void isr_rx(void *param) nse = 0U; hcto = 0U; - LL_ASSERT(false); + LL_ASSERT_DBG(false); } if (trx_cnt) { @@ -1352,34 +1352,37 @@ static void isr_rx(void *param) hcto -= addr_us_get(lll->phy); hcto -= radio_rx_ready_delay_get(lll->phy, PHY_FLAGS_S8); - overhead_us = radio_rx_chain_delay_get(lll->phy, PHY_FLAGS_S8); - overhead_us += addr_us_get(lll->phy); - overhead_us += radio_rx_ready_delay_get(lll->phy, PHY_FLAGS_S8); + /* Overhead within EVENT_IFS_US to exclude from max. jitter */ + /* Required radio ready duration, settling time */ + overhead_us = radio_rx_ready_delay_get(lll->phy, PHY_FLAGS_S8); + /* If single timer used, then consider required max. latency */ + overhead_us += HAL_RADIO_ISR_LATENCY_MAX_US; + /* Add chain delay overhead */ + overhead_us += radio_rx_chain_delay_get(lll->phy, PHY_FLAGS_S8); + /* Add base clock jitter overhead */ overhead_us += (EVENT_CLOCK_JITTER_US << 1); + LL_ASSERT_DBG(EVENT_IFS_US > overhead_us); - LL_ASSERT(EVENT_IFS_US > overhead_us); - + /* Max. available clock jitter */ jitter_max_us = (EVENT_IFS_US - overhead_us) >> 1; + /* Max. clock jitter per subevent */ jitter_max_us = (jitter_max_us * nse) / (lll->num_bis * lll->nse); - overhead_us = HAL_RADIO_TMR_START_DELAY_US; - if (jitter_max_us > overhead_us) { - jitter_max_us -= overhead_us; - } else { - jitter_max_us = 0U; - } + /* Min. clock jitter we shall use */ + jitter_max_us = MAX(jitter_max_us, (EVENT_CLOCK_JITTER_US << 1)); + /* Jitter for current subevent */ jitter_us = (EVENT_CLOCK_JITTER_US << 1) * nse; if (jitter_us > jitter_max_us) { jitter_us = jitter_max_us; } - LL_ASSERT(hcto > jitter_us); + LL_ASSERT_DBG(hcto > jitter_us); hcto -= jitter_us; start_us = hcto; hcto = radio_tmr_start_us(0U, start_us); - LL_ASSERT(hcto == (start_us + 1U)); + LL_ASSERT_ERR(hcto == (start_us + 1U)); /* Add 8 us * subevents so far, as radio was setup to listen * 4 us early and subevents could have a 4 us drift each until @@ -1396,7 +1399,7 @@ static void isr_rx(void *param) start_us = hcto; hcto = radio_tmr_start_us(0U, start_us); - LL_ASSERT(hcto == (start_us + 1U)); + LL_ASSERT_ERR(hcto == (start_us + 1U)); hcto += ((EVENT_JITTER_US + EVENT_TICKER_RES_MARGIN_US + lll->window_widening_event_us) << 1) + @@ -1445,7 +1448,7 @@ static void isr_rx(void *param) #endif /* CONFIG_BT_CTLR_SYNC_ISO_INTERLEAVED */ } else { - LL_ASSERT(false); + LL_ASSERT_DBG(false); } if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) { @@ -1543,7 +1546,7 @@ static void isr_rx_done(void *param) } e = ull_event_done_extra_get(); - LL_ASSERT(e); + LL_ASSERT_ERR(e); /* Check if BIG terminate procedure received */ if (lll->term_reason) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c index 9715b934e5e8..c724bd08e0bb 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c @@ -238,7 +238,7 @@ static void isr_rx(void *param) if (test_cte_len > 0) { /* Get free iq report node for next Rx operation. */ node_rx = ull_df_iq_report_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_df_iq_data_packet_set(node_rx->pdu, IQ_SAMPLE_TOTAL_CNT); } @@ -435,7 +435,7 @@ static uint8_t cte_rx_init(uint8_t expected_cte_len, uint8_t expected_cte_type, struct node_rx_iq_report *node_rx; node_rx = ull_df_iq_report_alloc_peek(1); - LL_ASSERT(node_rx); + LL_ASSERT_DBG(node_rx); radio_df_iq_data_packet_set(node_rx->pdu, IQ_SAMPLE_TOTAL_CNT); #else @@ -498,7 +498,7 @@ static uint8_t init(uint8_t chan, uint8_t phy, int8_t tx_power, /* Setup resources required by Radio */ err = lll_hfclock_on_wait(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Reset Radio h/w */ radio_reset(); @@ -744,7 +744,7 @@ uint8_t ll_test_end(uint16_t *num_rx) /* Release resources acquired for Radio */ err = lll_hfclock_off(); - LL_ASSERT(err >= 0); + LL_ASSERT_ERR(err >= 0); /* Stop coarse timer */ cntr_stop(); diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index bf15820ecd6d..4ff06e60fda9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -627,7 +627,7 @@ int ll_init(struct k_sem *sem_rx) hal_ticker_instance0_caller_id_get, hal_ticker_instance0_sched, hal_ticker_instance0_trigger_set); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); /* Initialize semaphore for ticker API blocking wait */ k_sem_init(&sem_ticker_api_cb, 0, 1); @@ -816,12 +816,12 @@ void ll_reset(void) #if defined(CONFIG_BT_CTLR_ADV_ISO) /* Reset adv iso sets */ err = ull_adv_iso_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_CTLR_ADV_ISO */ /* Reset adv state */ err = ull_adv_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_BROADCASTER */ #if defined(CONFIG_BT_OBSERVER) @@ -829,43 +829,43 @@ void ll_reset(void) #if defined(CONFIG_BT_CTLR_SYNC_ISO) /* Reset sync iso sets */ err = ull_sync_iso_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_CTLR_SYNC_ISO */ /* Reset periodic sync sets */ err = ull_sync_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ /* Reset scan state */ err = ull_scan_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_OBSERVER */ #if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) err = ull_peripheral_iso_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */ #if defined(CONFIG_BT_CTLR_CENTRAL_ISO) err = ull_central_iso_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_CTLR_CENTRAL_ISO */ #if defined(CONFIG_BT_CTLR_CONN_ISO) err = ull_conn_iso_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_CTLR_CONN_ISO */ #if defined(CONFIG_BT_CTLR_ISO) err = ull_iso_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_CTLR_ISO */ #if defined(CONFIG_BT_CONN) /* Reset conn role */ err = ull_conn_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); MFIFO_INIT(tx_ack); #endif /* CONFIG_BT_CONN */ @@ -912,7 +912,7 @@ void ll_reset(void) retval = mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!retval); + LL_ASSERT_ERR(!retval); #if !defined(CONFIG_BT_CTLR_ZLI) /* LLL reset must complete before returning - wait for @@ -925,7 +925,7 @@ void ll_reset(void) #if defined(CONFIG_BT_BROADCASTER) /* Finalize after adv state LLL context reset */ err = ull_adv_reset_finalize(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_BROADCASTER */ /* Reset/End DTM Tx or Rx commands */ @@ -938,7 +938,7 @@ void ll_reset(void) /* Common to init and reset */ err = init_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #if defined(CONFIG_BT_CTLR_DF) /* Direction Finding has to be reset after ull init_reset call because @@ -946,7 +946,7 @@ void ll_reset(void) * in common ull init_reset. */ err = ull_df_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif #if defined(CONFIG_BT_CTLR_SET_HOST_FEATURE) @@ -1101,7 +1101,7 @@ void ll_rx_dequeue(void) link = memq_dequeue(memq_ll_rx.tail, &memq_ll_rx.head, (void **)&rx); - LL_ASSERT(link); + LL_ASSERT_DBG(link); ll_rx_link_release(link); @@ -1129,7 +1129,7 @@ void ll_rx_dequeue(void) while (rx_curr) { memq_link_t *link_free; - LL_ASSERT(loop); + LL_ASSERT_ERR(loop); loop--; link_free = rx_curr->hdr.link; @@ -1154,7 +1154,7 @@ void ll_rx_dequeue(void) struct lll_adv_aux *lll_aux; adv = ull_adv_set_get(rx->hdr.handle); - LL_ASSERT(adv); + LL_ASSERT_DBG(adv); lll_aux = adv->lll.aux; if (lll_aux) { @@ -1174,11 +1174,11 @@ void ll_rx_dequeue(void) break; } - LL_ASSERT(!lll_conn->link_tx_free); + LL_ASSERT_DBG(!lll_conn->link_tx_free); memq_link_t *memq_link = memq_deinit(&lll_conn->memq_tx.head, &lll_conn->memq_tx.tail); - LL_ASSERT(memq_link); + LL_ASSERT_DBG(memq_link); lll_conn->link_tx_free = memq_link; @@ -1223,13 +1223,13 @@ void ll_rx_dequeue(void) memq_link_t *memq_link; conn_lll = lll->conn; - LL_ASSERT(conn_lll); + LL_ASSERT_DBG(conn_lll); lll->conn = NULL; - LL_ASSERT(!conn_lll->link_tx_free); + LL_ASSERT_DBG(!conn_lll->link_tx_free); memq_link = memq_deinit(&conn_lll->memq_tx.head, &conn_lll->memq_tx.tail); - LL_ASSERT(memq_link); + LL_ASSERT_DBG(memq_link); conn_lll->link_tx_free = memq_link; conn = HDR_LLL2ULL(conn_lll); @@ -1294,7 +1294,7 @@ void ll_rx_dequeue(void) scan->is_enabled = 0U; #else /* !CONFIG_BT_CENTRAL */ } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); #endif /* !CONFIG_BT_CENTRAL */ } @@ -1416,11 +1416,11 @@ void ll_rx_dequeue(void) * code block. */ case NODE_RX_TYPE_NONE: - LL_ASSERT(rx->hdr.type != NODE_RX_TYPE_NONE); + LL_ASSERT_DBG(rx->hdr.type != NODE_RX_TYPE_NONE); break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -1432,11 +1432,11 @@ void ll_rx_dequeue(void) struct ll_scan_set *scan; adv = ull_adv_is_enabled_get(0); - LL_ASSERT(adv); + LL_ASSERT_DBG(adv); adv->is_enabled = 0U; scan = ull_scan_is_enabled_get(0); - LL_ASSERT(scan); + LL_ASSERT_DBG(scan); scan->is_enabled = 0U; @@ -1520,7 +1520,7 @@ void ll_rx_mem_release(void **node_rx) #endif /* CONFIG_BT_CENTRAL */ } else { - LL_ASSERT(!cc->status); + LL_ASSERT_DBG(!cc->status); } } @@ -1607,7 +1607,7 @@ void ll_rx_mem_release(void **node_rx) * code block. */ case NODE_RX_TYPE_NONE: - LL_ASSERT(rx_free->hdr.type != NODE_RX_TYPE_NONE); + LL_ASSERT_DBG(rx_free->hdr.type != NODE_RX_TYPE_NONE); ll_rx_link_quota_inc(); ll_rx_release(rx_free); break; @@ -1652,7 +1652,7 @@ void ll_rx_mem_release(void **node_rx) break; } else { - LL_ASSERT(status == BT_HCI_ERR_OP_CANCELLED_BY_HOST); + LL_ASSERT_DBG(status == BT_HCI_ERR_OP_CANCELLED_BY_HOST); /* Fall through and release sync context */ } @@ -1716,12 +1716,12 @@ void ll_rx_mem_release(void **node_rx) memq_link_t *link; conn = ll_conn_get(rx_free->hdr.handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); - LL_ASSERT(!conn->lll.link_tx_free); + LL_ASSERT_DBG(!conn->lll.link_tx_free); link = memq_deinit(&conn->lll.memq_tx.head, &conn->lll.memq_tx.tail); - LL_ASSERT(link); + LL_ASSERT_DBG(link); conn->lll.link_tx_free = link; ll_conn_release(conn); @@ -1735,7 +1735,7 @@ void ll_rx_mem_release(void **node_rx) case NODE_RX_TYPE_EVENT_DONE: default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } @@ -1747,7 +1747,7 @@ void ll_rx_mem_release(void **node_rx) static void ll_rx_link_quota_update(int8_t delta) { - LL_ASSERT(delta <= 0 || mem_link_rx.quota_pdu < RX_CNT); + LL_ASSERT_DBG(delta <= 0 || mem_link_rx.quota_pdu < RX_CNT); mem_link_rx.quota_pdu += delta; } @@ -1837,7 +1837,7 @@ void ll_tx_ack_put(uint16_t handle, struct node_tx *node_tx) uint8_t idx; idx = MFIFO_ENQUEUE_GET(tx_ack, (void **)&tx); - LL_ASSERT(tx); + LL_ASSERT_ERR(tx); tx->handle = handle; tx->node = node_tx; @@ -1868,7 +1868,7 @@ void ll_radio_state_abort(void) ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } uint32_t ll_radio_state_is_idle(void) @@ -2053,7 +2053,7 @@ int ull_disable(void *lll) mfy.param = lll; ret = mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); err = k_sem_take(&sem, ULL_DISABLE_TIMEOUT); if (err != 0) { @@ -2195,7 +2195,7 @@ void ull_prepare_dequeue(uint8_t caller_id) /* Assert if we exceed iterations processing the prepare queue */ - LL_ASSERT(loop); + LL_ASSERT_ERR(loop); loop--; /* Let LLL invoke the `prepare` interface if radio not in active @@ -2210,7 +2210,7 @@ void ull_prepare_dequeue(uint8_t caller_id) mfy.param = next; ret = mayfly_enqueue(caller_id, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } MFIFO_DEQUEUE(prep); @@ -2391,14 +2391,14 @@ static inline int init_reset(void) /* Acquire a link to initialize ull rx memq */ link = mem_acquire(&mem_link_rx.free); - LL_ASSERT(link); + LL_ASSERT_DBG(link); /* Initialize ull rx memq */ MEMQ_INIT(ull_rx, link); /* Acquire a link to initialize ll rx memq */ link = mem_acquire(&mem_link_rx.free); - LL_ASSERT(link); + LL_ASSERT_DBG(link); /* Initialize ll rx memq */ MEMQ_INIT(ll_rx, link); @@ -2428,29 +2428,29 @@ static void perform_lll_reset(void *param) /* Reset LLL */ err = lll_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #if defined(CONFIG_BT_BROADCASTER) /* Reset adv state */ err = lll_adv_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_BROADCASTER */ #if defined(CONFIG_BT_OBSERVER) /* Reset scan state */ err = lll_scan_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_OBSERVER */ #if defined(CONFIG_BT_CONN) /* Reset conn role */ err = lll_conn_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_CTLR_DF) err = lll_df_reset(); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #endif /* CONFIG_BT_CTLR_DF */ #if !defined(CONFIG_BT_CTLR_ZLI) @@ -2611,7 +2611,7 @@ static void rx_demux(void *param) link = memq_peek(memq_ull_rx.head, memq_ull_rx.tail, (void **)&rx); if (link) { - LL_ASSERT(rx); + LL_ASSERT_DBG(rx); #if defined(CONFIG_BT_CONN) link_tx = ull_conn_ack_by_last_peek(rx->ack_last, &handle, &tx); @@ -2910,7 +2910,7 @@ static inline void rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx) (void)memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL); conn = ll_conn_get(rx->handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); if (ull_cp_cc_awaiting_established(conn)) { ull_cp_cc_established(conn, BT_HCI_ERR_SUCCESS); @@ -3021,7 +3021,7 @@ static inline void rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx) rx_demux_rx_proprietary(link, rx, memq_ull_rx.tail, &memq_ull_rx.head); #else - LL_ASSERT(0); + LL_ASSERT_DBG(0); #endif /* CONFIG_BT_CTLR_USER_EXT */ } break; @@ -3037,7 +3037,7 @@ static inline void rx_demux_event_done(memq_link_t *link, /* Decrement prepare reference if ULL will not resume */ ull_hdr = done->param; if (ull_hdr) { - LL_ASSERT(ull_ref_get(ull_hdr)); + LL_ASSERT_DBG(ull_ref_get(ull_hdr)); ull_ref_dec(ull_hdr); } else { /* No reference count decrement, event placed back as resume event in the pipeline. @@ -3127,14 +3127,14 @@ static inline void rx_demux_event_done(memq_link_t *link, break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } /* Release done */ done->extra.type = 0U; release = RXFIFO_RELEASE(done, link, done); - LL_ASSERT(release == done); + LL_ASSERT_DBG(release == done); #if defined(CONFIG_BT_CTLR_LOW_LAT_ULL_DONE) /* dequeue prepare pipeline */ @@ -3218,7 +3218,7 @@ void *ull_rxfifo_release(uint8_t s, uint8_t n, uint8_t f, uint8_t *l, uint8_t *m */ uint32_t ull_get_wrapped_time_us(uint32_t time_now_us, int32_t time_diff_us) { - LL_ASSERT(time_now_us <= ULL_TIME_WRAPPING_POINT_US); + LL_ASSERT_DBG(time_now_us <= ULL_TIME_WRAPPING_POINT_US); uint32_t result = ((uint64_t)time_now_us + ULL_TIME_SPAN_FULL_US + time_diff_us) % ((uint64_t)ULL_TIME_SPAN_FULL_US); diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index 18f3f24b11db..f9f1ee78afe4 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -206,7 +206,7 @@ uint8_t ll_adv_set_hci_handle_get(uint8_t handle) struct ll_adv_set *adv; adv = ull_adv_set_get(handle); - LL_ASSERT(adv && adv->is_created); + LL_ASSERT_DBG(adv && adv->is_created); return adv->hci_handle; } @@ -442,8 +442,8 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type, if (pdu->len == 0U) { adv->ad_data_backup.len = 0U; } else { - LL_ASSERT(pdu->len >= - offsetof(struct pdu_adv_adv_ind, data)); + LL_ASSERT_DBG(pdu->len >= + offsetof(struct pdu_adv_adv_ind, data)); adv->ad_data_backup.len = pdu->len - offsetof(struct pdu_adv_adv_ind, data); @@ -1970,9 +1970,9 @@ static uint32_t ticker_update_rand(struct ll_adv_set *adv, uint32_t ticks_delay_ ticks_adjust_minus, 0, 0, 0, 0, fp_op_func, adv); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY) || - (fp_op_func == NULL)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY) || + (fp_op_func == NULL)); return random_delay; } @@ -2090,7 +2090,7 @@ void ull_adv_done(struct node_rx_event_done *done) } handle = ull_adv_handle_get(adv); - LL_ASSERT(handle < BT_CTLR_ADV_SET); + LL_ASSERT_DBG(handle < BT_CTLR_ADV_SET); rx->hdr.type = NODE_RX_TYPE_EXT_ADV_TERMINATE; rx->hdr.handle = handle; @@ -2115,8 +2115,8 @@ void ull_adv_done(struct node_rx_event_done *done) ticker_stop_ext_op_cb, adv); } - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); #endif /* CONFIG_BT_CTLR_ADV_EXT */ } #endif /* CONFIG_BT_CTLR_ADV_EXT || CONFIG_BT_CTLR_JIT_SCHEDULING */ @@ -2369,7 +2369,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, (lazy != TICKER_LAZY_MUST_EXPIRE)) { /* Increment prepare reference count */ ref = ull_ref_inc(&adv->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); #if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) && \ defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) @@ -2377,7 +2377,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t ticks_to_expire; uint32_t other_remainder = 0U; - LL_ASSERT(context->other_expire_info); + LL_ASSERT_DBG(context->other_expire_info); /* Adjust ticks to expire based on remainder value */ ticks_to_expire = context->other_expire_info->ticks_to_expire; @@ -2405,7 +2405,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); #if defined(CONFIG_BT_CTLR_JIT_SCHEDULING) || \ (defined(CONFIG_BT_CTLR_ADV_EXT) && \ @@ -2496,7 +2496,7 @@ static void ticker_update_op_cb(uint32_t status, void *param) /* Reset update requested */ ticker_update_ack = ticker_update_req; -#if defined(CONFIG_BT_PERIPHERAL) && (defined(CONFIG_BT_ASSERT) || defined(CONFIG_ASSERT)) +#if defined(CONFIG_BT_PERIPHERAL) struct ll_adv_set *adv = param; struct pdu_adv *pdu = lll_adv_data_peek(&adv->lll); bool connectable = (pdu->type == PDU_ADV_TYPE_ADV_IND) || @@ -2508,13 +2508,13 @@ static void ticker_update_op_cb(uint32_t status, void *param) 0; #endif /* CONFIG_BT_PERIPHERAL && (CONFIG_BT_ASSERT || CONFIG_ASSERT) */ - LL_ASSERT(status == TICKER_STATUS_SUCCESS || - param == ull_disable_mark_get() || + LL_ASSERT_ERR((status == TICKER_STATUS_SUCCESS) || + (param == ull_disable_mark_get()) || #if defined(CONFIG_BT_PERIPHERAL) - /* if using connectable adv and lll.conn is 0 -> a connection is underway */ - (connectable && !adv->lll.conn) || + /* if using connectable adv and lll.conn is 0 -> a connection is underway */ + (connectable && !adv->lll.conn) || #endif /* CONFIG_BT_PERIPHERAL */ - 0); + 0); } #if defined(CONFIG_BT_PERIPHERAL) @@ -2527,13 +2527,13 @@ static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t ret; handle = ull_adv_handle_get(adv); - LL_ASSERT(handle < BT_CTLR_ADV_SET); + LL_ASSERT_DBG(handle < BT_CTLR_ADV_SET); ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, TICKER_ID_ADV_BASE + handle, ticker_stop_op_cb, adv); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } static void ticker_stop_op_cb(uint32_t status, void *param) @@ -2560,7 +2560,7 @@ static void ticker_stop_op_cb(uint32_t status, void *param) mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void adv_disable(void *param) @@ -2581,14 +2581,14 @@ static void adv_disable(void *param) /* Setup disabled callback to be called when ref count * returns to zero. */ - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = mfy.param; hdr->disabled_cb = disabled_cb; /* Trigger LLL disable */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } else { /* No pending LLL events */ disabled_cb(&adv->lll); @@ -2604,11 +2604,11 @@ static void disabled_cb(void *param) adv = ((struct lll_hdr *)param)->parent; - LL_ASSERT(adv->link_cc_free); + LL_ASSERT_DBG(adv->link_cc_free); link = adv->link_cc_free; adv->link_cc_free = NULL; - LL_ASSERT(adv->node_rx_cc_free); + LL_ASSERT_DBG(adv->node_rx_cc_free); rx = adv->node_rx_cc_free; adv->node_rx_cc_free = NULL; @@ -2628,7 +2628,7 @@ static void disabled_cb(void *param) ll_rx_put(link, rx); handle = ull_adv_handle_get(adv); - LL_ASSERT(handle < BT_CTLR_ADV_SET); + LL_ASSERT_DBG(handle < BT_CTLR_ADV_SET); rx = (void *)adv->lll.node_rx_adv_term; rx->hdr.type = NODE_RX_TYPE_EXT_ADV_TERMINATE; @@ -2649,9 +2649,9 @@ static void conn_release(struct ll_adv_set *adv) struct lll_conn *lll = adv->lll.conn; memq_link_t *link; - LL_ASSERT(!lll->link_tx_free); + LL_ASSERT_DBG(!lll->link_tx_free); link = memq_deinit(&lll->memq_tx.head, &lll->memq_tx.tail); - LL_ASSERT(link); + LL_ASSERT_DBG(link); lll->link_tx_free = link; ll_conn_release(lll->hdr.parent); @@ -2702,13 +2702,13 @@ static void ticker_stop_aux_op_cb(uint32_t status, void *param) static struct mayfly mfy = {0, 0, &link, NULL, aux_disable}; uint32_t ret; - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); /* Check if any pending LLL events that need to be aborted */ mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void aux_disable(void *param) @@ -2723,7 +2723,7 @@ static void aux_disable(void *param) aux = HDR_LLL2ULL(lll_aux); hdr = &aux->ull; if (ull_ref_get(hdr)) { - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = adv; hdr->disabled_cb = aux_disabled_cb; } else { @@ -2741,8 +2741,8 @@ static void aux_disabled_cb(void *param) TICKER_USER_ID_ULL_HIGH, (TICKER_ID_ADV_BASE + handle), ticker_stop_ext_op_cb, param); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } static void ticker_stop_ext_op_cb(uint32_t status, void *param) @@ -2762,7 +2762,7 @@ static void ticker_stop_ext_op_cb(uint32_t status, void *param) mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void ext_disable(void *param) @@ -2783,14 +2783,14 @@ static void ext_disable(void *param) /* Setup disabled callback to be called when ref count * returns to zero. */ - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = mfy.param; hdr->disabled_cb = ext_disabled_cb; /* Trigger LLL disable */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } else { /* No pending LLL events */ ext_disabled_cb(&adv->lll); @@ -2852,7 +2852,7 @@ static inline uint8_t disable(uint8_t handle) #endif /* CONFIG_BT_PERIPHERAL */ mark = ull_disable_mark(adv); - LL_ASSERT(mark == adv); + LL_ASSERT_DBG(mark == adv); #if defined(CONFIG_BT_PERIPHERAL) if (adv->lll.is_hdcd) { @@ -2863,7 +2863,7 @@ static inline uint8_t disable(uint8_t handle) ret = ull_ticker_status_take(ret, &ret_cb); if (ret) { mark = ull_disable_unmark(adv); - LL_ASSERT(mark == adv); + LL_ASSERT_DBG(mark == adv); return BT_HCI_ERR_CMD_DISALLOWED; } @@ -2877,16 +2877,16 @@ static inline uint8_t disable(uint8_t handle) ret = ull_ticker_status_take(ret, &ret_cb); if (ret) { mark = ull_disable_unmark(adv); - LL_ASSERT(mark == adv); + LL_ASSERT_DBG(mark == adv); return BT_HCI_ERR_CMD_DISALLOWED; } err = ull_disable(&adv->lll); - LL_ASSERT(!err || (err == -EALREADY)); + LL_ASSERT_ERR(!err || (err == -EALREADY)); mark = ull_disable_unmark(adv); - LL_ASSERT(mark == adv); + LL_ASSERT_DBG(mark == adv); #if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) struct lll_adv_aux *lll_aux = adv->lll.aux; @@ -3043,7 +3043,7 @@ static inline uint8_t *adv_pdu_adva_get(struct pdu_adv *pdu) /* All extended PDUs have AdvA at the same offset in common header */ if (pdu->type == PDU_ADV_TYPE_EXT_IND) { - LL_ASSERT(hdr_flags.adv_addr); + LL_ASSERT_DBG(hdr_flags.adv_addr); return &com_hdr->ext_hdr_adv_data[1]; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c index d77c004069e0..8701f3f65fa9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c @@ -256,7 +256,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, /* Get the reference to auxiliary PDU chain */ pdu_prev = lll_adv_aux_data_alloc(adv->lll.aux, &idx); - LL_ASSERT(idx == sec_idx); + LL_ASSERT_DBG(idx == sec_idx); /* Current auxiliary PDU */ pdu = pdu_prev; @@ -269,7 +269,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, pdu_parent = lll_adv_aux_data_alloc(adv->lll.aux, &idx); - LL_ASSERT(idx == sec_idx); + LL_ASSERT_DBG(idx == sec_idx); /* Remove/Release any previous chain PDU * allocations @@ -340,7 +340,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, 0U, hdr_data); ad_len_prev = hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET]; - LL_ASSERT(!err || (err == BT_HCI_ERR_PACKET_TOO_LONG)); + LL_ASSERT_DBG(!err || (err == BT_HCI_ERR_PACKET_TOO_LONG)); /* Check of max supported AD data len */ ad_len_total += ad_len_prev; @@ -363,8 +363,8 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, pdu_chain_prev = lll_adv_pdu_linked_next_get(pdu_prev); pdu_chain = lll_adv_pdu_linked_next_get(pdu); - LL_ASSERT((pdu_chain_prev && pdu_chain) || - (!pdu_chain_prev && !pdu_chain)); + LL_ASSERT_DBG((pdu_chain_prev && pdu_chain) || + (!pdu_chain_prev && !pdu_chain)); } while (pdu_chain_prev); /* No AD data overflow */ @@ -408,7 +408,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND, 0U, hdr_data); - LL_ASSERT((!chain_err) || (chain_err == BT_HCI_ERR_PACKET_TOO_LONG)); + LL_ASSERT_DBG((!chain_err) || (chain_err == BT_HCI_ERR_PACKET_TOO_LONG)); /* FIXME: the code has become quite complex, an alternative and simpler * implementation would be to first fill an array with all data that @@ -456,7 +456,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, chain_err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu, chain_add_fields, 0U, hdr_data); - LL_ASSERT(chain_err == 0U); + LL_ASSERT_DBG(chain_err == 0U); /* * in the next PDU we still need to add ad_len_chain bytes of data * but we do not have overflow, since we already added @@ -495,7 +495,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, /* Allocate new PDU */ pdu_chain = lll_adv_pdu_alloc_pdu_adv(); - LL_ASSERT(pdu_chain); + LL_ASSERT_ERR(pdu_chain); /* Populate the appended chain PDU */ pdu_chain->type = PDU_ADV_TYPE_AUX_CHAIN_IND; @@ -509,7 +509,8 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, hdr_chain = (void *)&com_hdr_chain->ext_hdr_adv_data[0]; dptr_chain = (void *)hdr_chain; - LL_ASSERT(dptr_chain); + LL_ASSERT_DBG(dptr_chain); + /* Flags */ *dptr_chain = 0U; @@ -781,7 +782,7 @@ uint8_t ll_adv_aux_sr_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, } /* Scannable advertising shall have aux context allocated */ - LL_ASSERT(lll->aux); + LL_ASSERT_DBG(lll->aux); /* Get reference to previous secondary channel PDU */ sec_pdu_prev = lll_adv_aux_data_peek(lll->aux); @@ -1046,7 +1047,7 @@ uint8_t ll_adv_aux_sr_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, err = ull_adv_aux_pdu_set_clear(adv, sr_pdu_prev, sr_pdu, hdr_add_fields, 0U, hdr_data); - LL_ASSERT(!err || (err == BT_HCI_ERR_PACKET_TOO_LONG)); + LL_ASSERT_DBG(!err || (err == BT_HCI_ERR_PACKET_TOO_LONG)); /* Get PDUs previous AD data length */ ad_len_prev = @@ -1073,8 +1074,8 @@ uint8_t ll_adv_aux_sr_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, pdu_chain_prev = lll_adv_pdu_linked_next_get(sr_pdu_prev); pdu_chain = lll_adv_pdu_linked_next_get(sr_pdu); - LL_ASSERT((pdu_chain_prev && pdu_chain) || - (!pdu_chain_prev && !pdu_chain)); + LL_ASSERT_DBG((pdu_chain_prev && pdu_chain) || + (!pdu_chain_prev && !pdu_chain)); } while (pdu_chain_prev); if (err == BT_HCI_ERR_PACKET_TOO_LONG) { @@ -1141,7 +1142,7 @@ uint8_t ll_adv_aux_sr_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, /* Allocate new PDU */ pdu_chain = lll_adv_pdu_alloc_pdu_adv(); - LL_ASSERT(pdu_chain); + LL_ASSERT_ERR(pdu_chain); /* Populate the appended chain PDU */ pdu_chain->type = PDU_ADV_TYPE_AUX_CHAIN_IND; @@ -1528,8 +1529,8 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv, lll = &adv->lll; /* Can't have both flags set here since both use 'hdr_data' param */ - LL_ASSERT(!(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) || - !(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA)); + LL_ASSERT_DBG(!(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) || + !(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA)); /* Get reference to previous primary PDU data */ pri_pdu_prev = lll_adv_data_peek(lll); @@ -1579,7 +1580,7 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv, if (!lll_aux) { aux = ull_adv_aux_acquire(lll); if (!aux) { - LL_ASSERT(pri_pdu != pri_pdu_prev); + LL_ASSERT_DBG(pri_pdu != pri_pdu_prev); return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } @@ -2566,7 +2567,7 @@ void ull_adv_sync_started_stopped(struct ll_adv_aux_set *aux) struct ll_adv_sync_set *sync; uint8_t aux_handle; - LL_ASSERT(lll_sync); + LL_ASSERT_DBG(lll_sync); sync = HDR_LLL2ULL(lll_sync); aux_handle = ull_adv_aux_handle_get(aux); @@ -2760,7 +2761,7 @@ void ull_adv_aux_offset_get(struct ll_adv_set *adv) mfy.param = adv; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */ @@ -2886,7 +2887,7 @@ void ull_adv_aux_chain_pdu_duplicate(struct pdu_adv *pdu_prev, if (!pdu_chain) { /* Get a new chain PDU */ pdu_chain = lll_adv_pdu_alloc_pdu_adv(); - LL_ASSERT(pdu_chain); + LL_ASSERT_ERR(pdu_chain); /* Copy previous chain PDU into new chain PDU */ (void)memcpy(pdu_chain, pdu_chain_prev, @@ -3240,7 +3241,7 @@ static void mfy_aux_offset_get(void *param) } success = (ret_cb == TICKER_STATUS_SUCCESS); - LL_ASSERT(success); + LL_ASSERT_ERR(success); /* FIXME: If the reference ticks change then implement the * compensation by adding the difference to the @@ -3249,9 +3250,9 @@ static void mfy_aux_offset_get(void *param) * ticker expiry that update the ticks_current. * For now assert until the fix implementation is added. */ - LL_ASSERT((ticks_current == ticks_previous) || retry--); + LL_ASSERT_ERR((ticks_current == ticks_previous) || retry--); - LL_ASSERT(id != TICKER_NULL); + LL_ASSERT_ERR(id != TICKER_NULL); } while (id != ticker_id); /* Adjust ticks to expire based on remainder value */ @@ -3326,7 +3327,7 @@ static void mfy_aux_offset_get(void *param) ticks_elapsed = ticker_ticks_diff_get(ticks_now, ticks_current); ticks_to_start = HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US) - HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US); - LL_ASSERT(ticks_elapsed < ticks_to_start); + LL_ASSERT_ERR(ticks_elapsed < ticks_to_start); } static void ticker_op_cb(uint32_t status, void *param) @@ -3358,7 +3359,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&aux->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) @@ -3374,7 +3375,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t ticks_to_expire; uint32_t sync_remainder_us = 0U; - LL_ASSERT(context->other_expire_info); + LL_ASSERT_DBG(context->other_expire_info); /* Reduce a tick for negative remainder and return positive remainder * value. @@ -3418,7 +3419,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) struct ll_adv_set *adv; @@ -3441,8 +3442,8 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) static void ticker_update_op_cb(uint32_t status, void *param) { - LL_ASSERT(status == TICKER_STATUS_SUCCESS || - param == ull_disable_mark_get()); + LL_ASSERT_ERR((status == TICKER_STATUS_SUCCESS) || + (param == ull_disable_mark_get())); } #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c index f8f7cb35d64a..775baf1c63e7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c @@ -507,7 +507,7 @@ static uint8_t big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bi lll_adv_iso->max_sdu = max_sdu; res = util_saa_le32(lll_adv_iso->seed_access_addr, big_handle); - LL_ASSERT(!res); + LL_ASSERT_DBG(!res); (void)lll_csrand_get(lll_adv_iso->base_crc_init, sizeof(lll_adv_iso->base_crc_init)); @@ -604,11 +604,11 @@ static uint8_t big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bi /* Calculate GSK */ err = bt_crypto_h7(BIG1, bcode, igltk); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); err = bt_crypto_h6(igltk, BIG2, gltk); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); err = bt_crypto_h8(gltk, big_info->gskd, BIG3, gsk); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); /* Prepare the CCM parameters */ ccm_tx = &lll_adv_iso->ccm_tx; @@ -820,7 +820,7 @@ int ull_adv_iso_reset(void) } mark = ull_disable_mark(adv_iso); - LL_ASSERT(mark == adv_iso); + LL_ASSERT_DBG(mark == adv_iso); /* Stop event scheduling */ ret_cb = TICKER_STATUS_BUSY; @@ -830,20 +830,20 @@ int ull_adv_iso_reset(void) ret = ull_ticker_status_take(ret, &ret_cb); if (ret) { mark = ull_disable_unmark(adv_iso); - LL_ASSERT(mark == adv_iso); + LL_ASSERT_DBG(mark == adv_iso); /* Assert as there shall be a ticker instance active */ - LL_ASSERT(false); + LL_ASSERT_DBG(false); return BT_HCI_ERR_CMD_DISALLOWED; } /* Abort any events in LLL pipeline */ err = ull_disable(adv_iso_lll); - LL_ASSERT(!err || (err == -EALREADY)); + LL_ASSERT_ERR(!err || (err == -EALREADY)); mark = ull_disable_unmark(adv_iso); - LL_ASSERT(mark == adv_iso); + LL_ASSERT_DBG(mark == adv_iso); /* Reset associated streams */ while (adv_iso_lll->num_bis--) { @@ -970,7 +970,7 @@ void ull_adv_iso_offset_get(struct ll_adv_sync_set *sync) mfy.param = sync; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) @@ -1071,8 +1071,8 @@ void ull_adv_iso_done_terminate(struct node_rx_event_done *done) ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, (TICKER_ID_ADV_ISO_BASE + lll->handle), ticker_stop_op_cb, adv_iso); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); /* Invalidate the handle */ lll->handle = LLL_ADV_HANDLE_INVALID; @@ -1115,10 +1115,10 @@ void ull_adv_iso_stream_release(struct ll_adv_iso_set *adv_iso) stream_handle = lll->stream_handle[lll->num_bis]; stream = ull_adv_iso_stream_get(stream_handle); - LL_ASSERT(!stream->link_tx_free); + LL_ASSERT_DBG(!stream->link_tx_free); link = memq_deinit(&stream->memq_tx.head, &stream->memq_tx.tail); - LL_ASSERT(link); + LL_ASSERT_DBG(link); stream->link_tx_free = link; dp = stream->dp; @@ -1220,7 +1220,7 @@ static uint8_t ptc_calc(const struct lll_adv_iso *lll, uint32_t event_spacing, * running buffer offset related to nse. Fix ptc and ptc_curr definitions, * until then lets have an assert check here. */ - LL_ASSERT(ptc <= BIT_MASK(4)); + LL_ASSERT_DBG(ptc <= BIT_MASK(4)); return ptc; } @@ -1378,11 +1378,11 @@ static void adv_iso_chm_complete_commit(struct lll_adv_iso *lll_iso) adv = HDR_LLL2ULL(lll_iso->adv); err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST, &pdu_prev, &pdu, NULL, NULL, &ter_idx); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); /* Copy content */ err = ull_adv_sync_duplicate(pdu_prev, pdu); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); /* Get the current ACAD */ acad = ull_adv_sync_get_acad(pdu, &acad_len); @@ -1390,7 +1390,7 @@ static void adv_iso_chm_complete_commit(struct lll_adv_iso *lll_iso) lll_sync = adv->lll.sync; /* Dev assert if ACAD empty */ - LL_ASSERT(acad_len); + LL_ASSERT_DBG(acad_len); /* Find the BIGInfo */ len = acad_len; @@ -1404,12 +1404,13 @@ static void adv_iso_chm_complete_commit(struct lll_adv_iso *lll_iso) ad_len += 1U; - LL_ASSERT(ad_len <= len); + LL_ASSERT_DBG(ad_len <= len); ad += ad_len; len -= ad_len; } while (len); - LL_ASSERT(len); + + LL_ASSERT_DBG(len); /* Get reference to BIGInfo */ bi = (void *)&ad[PDU_ADV_DATA_HEADER_DATA_OFFSET]; @@ -1474,11 +1475,11 @@ static void mfy_iso_offset_get(void *param) } success = (ret_cb == TICKER_STATUS_SUCCESS); - LL_ASSERT(success); + LL_ASSERT_ERR(success); - LL_ASSERT((ticks_current == ticks_previous) || retry--); + LL_ASSERT_ERR((ticks_current == ticks_previous) || retry--); - LL_ASSERT(id != TICKER_NULL); + LL_ASSERT_ERR(id != TICKER_NULL); } while (id != ticker_id); payload_count = lll_iso->payload_count + @@ -1593,7 +1594,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&adv_iso->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); /* Append timing parameters */ p.ticks_at_expire = ticks_at_expire; @@ -1606,7 +1607,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy_lll_prepare); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); /* Calculate the BIG reference point of current BIG event */ remainder_us = remainder; @@ -1630,13 +1631,13 @@ static void ticker_stop_op_cb(uint32_t status, void *param) static struct mayfly mfy = {0U, 0U, &link, NULL, adv_iso_disable}; uint32_t ret; - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); /* Check if any pending LLL events that need to be aborted */ mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void adv_iso_disable(void *param) @@ -1657,14 +1658,14 @@ static void adv_iso_disable(void *param) /* Setup disabled callback to be called when ref count * returns to zero. */ - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = mfy.param; hdr->disabled_cb = disabled_cb; /* Trigger LLL disable */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } else { /* No pending LLL events */ disabled_cb(&adv_iso->lll); @@ -1680,7 +1681,7 @@ static void disabled_cb(void *param) mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void tx_lll_flush(void *param) @@ -1726,7 +1727,7 @@ static void tx_lll_flush(void *param) adv_iso = HDR_LLL2ULL(lll); rx = (void *)&adv_iso->node_rx_terminate; link = rx->hdr.link; - LL_ASSERT(link); + LL_ASSERT_DBG(link); rx->hdr.link = NULL; /* Enqueue the terminate towards ULL context */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c index 8c4d610b8874..ea1311c528e1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c @@ -176,7 +176,7 @@ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags) lll_hdr_init(lll_sync, sync); err = util_aa_le32(lll_sync->access_addr); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); lll_sync->data_chan_id = lll_chan_id(lll_sync->access_addr); chm_last = lll_sync->chm_first; @@ -940,11 +940,11 @@ void ull_adv_sync_chm_complete(struct node_rx_pdu *rx) adv = HDR_LLL2ULL(lll_sync->adv); err = ull_adv_sync_pdu_alloc(adv, ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST, &pdu_prev, &pdu, NULL, NULL, &ter_idx); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); err = ull_adv_sync_remove_from_acad(lll_sync, pdu_prev, pdu, PDU_ADV_DATA_TYPE_CHANNEL_MAP_UPDATE_IND); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); lll_adv_sync_data_enqueue(lll_sync, ter_idx); } @@ -981,7 +981,7 @@ void ull_adv_sync_offset_get(struct ll_adv_set *adv) mfy.param = adv; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */ @@ -1013,11 +1013,12 @@ void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags, *(uint8_t *)ext_hdr = ext_hdr_flags; dptr = ext_hdr->data; - LL_ASSERT(!(ext_hdr_flags & (ULL_ADV_PDU_HDR_FIELD_ADVA | ULL_ADV_PDU_HDR_FIELD_TARGETA | + LL_ASSERT_DBG(!(ext_hdr_flags & (ULL_ADV_PDU_HDR_FIELD_ADVA | + ULL_ADV_PDU_HDR_FIELD_TARGETA | #if !defined(CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT) - ULL_ADV_PDU_HDR_FIELD_ADI | + ULL_ADV_PDU_HDR_FIELD_ADI | #endif /* CONFIG_BT_CTLR_ADV_PERIODIC_ADI_SUPPORT */ - ULL_ADV_PDU_HDR_FIELD_SYNC_INFO))); + ULL_ADV_PDU_HDR_FIELD_SYNC_INFO))); #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK) if (IS_ENABLED(CONFIG_BT_CTLR_DF_ADV_CTE_TX) && @@ -1174,8 +1175,8 @@ static void ull_adv_sync_add_to_header(struct pdu_adv *pdu, /* Push back any adv data - overflow will be returned via ad_overflow */ if (pdu->len > hdr->ext_hdr_len + 1U) { if (pdu->len > PDU_AC_EXT_PAYLOAD_SIZE_MAX - delta) { - LL_ASSERT(ad_overflow); - LL_ASSERT(overflow_len); + LL_ASSERT_DBG(ad_overflow); + LL_ASSERT_DBG(overflow_len); #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_LINK) *overflow_len = delta - (PDU_AC_EXT_PAYLOAD_SIZE_MAX - pdu->len); memcpy(ad_overflow, @@ -1375,7 +1376,7 @@ static void ull_adv_sync_copy_pdu_header(struct pdu_adv *target_pdu, const uint8_t *source_dptr; uint8_t *target_dptr; - LL_ASSERT(target_pdu != source_pdu); + LL_ASSERT_DBG(target_pdu != source_pdu); /* Initialize PDU header */ target_pdu->type = source_pdu->type; @@ -1861,7 +1862,8 @@ static uint8_t ull_adv_sync_add_adi(struct lll_adv_sync *lll_sync, last_pdu = pdu; /* We should always have enough available overflow space to fit an ADI */ - LL_ASSERT(total_overflow_len + sizeof(struct pdu_adv_adi) <= sizeof(ad_overflow)); + LL_ASSERT_DBG((total_overflow_len + sizeof(struct pdu_adv_adi)) <= + sizeof(ad_overflow)); ull_adv_sync_add_to_header(pdu, &add_fields, &ad_overflow[total_overflow_len], &overflow_len); @@ -2054,7 +2056,7 @@ uint8_t ull_adv_sync_remove_from_acad(struct lll_adv_sync *lll_sync, ad_len += 1U; - LL_ASSERT(ad_len <= len); + LL_ASSERT_DBG(ad_len <= len); ad += ad_len; len -= ad_len; @@ -2180,7 +2182,8 @@ uint8_t ull_adv_sync_add_cteinfo(struct lll_adv_sync *lll_sync, last_pdu = pdu; /* We should always have enough available overflow space to fit CTEInfo */ - LL_ASSERT(total_overflow_len + sizeof(struct pdu_cte_info) <= sizeof(ad_overflow)); + LL_ASSERT_DBG((total_overflow_len + sizeof(struct pdu_cte_info)) <= + sizeof(ad_overflow)); ull_adv_sync_add_to_header(pdu, &add_fields, &ad_overflow[total_overflow_len], &overflow_len); @@ -2720,11 +2723,11 @@ static void mfy_sync_offset_get(void *param) } success = (ret_cb == TICKER_STATUS_SUCCESS); - LL_ASSERT(success); + LL_ASSERT_ERR(success); - LL_ASSERT((ticks_current == ticks_previous) || retry--); + LL_ASSERT_ERR((ticks_current == ticks_previous) || retry--); - LL_ASSERT(id != TICKER_NULL); + LL_ASSERT_ERR(id != TICKER_NULL); } while (id != ticker_id); /* Reduced a tick for negative remainder and return positive remainder @@ -2861,14 +2864,14 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&sync->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); #if defined(CONFIG_BT_CTLR_ADV_ISO) && \ defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) if (lll->iso) { struct lll_adv_iso *lll_iso = lll->iso; - LL_ASSERT(context->other_expire_info); + LL_ASSERT_DBG(context->other_expire_info); /* Check: No need for remainder in this case? */ lll_iso->ticks_sync_pdu_offset = context->other_expire_info->ticks_to_expire; @@ -2887,7 +2890,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); #if defined(CONFIG_BT_CTLR_ADV_ISO) && \ !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) @@ -2903,7 +2906,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) static void ticker_update_op_cb(uint32_t status, void *param) { - LL_ASSERT(status == TICKER_STATUS_SUCCESS || - param == ull_disable_mark_get()); + LL_ASSERT_ERR((status == TICKER_STATUS_SUCCESS) || + (param == ull_disable_mark_get())); } #endif /* !CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index 1771cda124bd..f4bc227cfdf5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -190,7 +190,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window, conn_lll = &conn->lll; err = util_aa_le32(conn_lll->access_addr); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); lll_csrand_get(conn_lll->crc_init, sizeof(conn_lll->crc_init)); @@ -519,7 +519,7 @@ uint8_t ll_connect_disable(void **rx) conn = HDR_LLL2ULL(conn_lll); node_rx = (void *)&conn->llcp_terminate.node_rx.rx; link = node_rx->hdr.link; - LL_ASSERT(link); + LL_ASSERT_DBG(link); /* free the memq link early, as caller could overwrite it */ ll_rx_link_release(link); @@ -603,7 +603,7 @@ int ull_central_reset(void) } } - LL_ASSERT(scan); + LL_ASSERT_DBG(scan); scan->is_enabled = 0U; scan->lll.conn = NULL; @@ -628,13 +628,13 @@ void ull_central_cleanup(struct node_rx_pdu *rx_free) */ scan = HDR_LLL2ULL(rx_free->rx_ftr.param); conn_lll = scan->lll.conn; - LL_ASSERT(conn_lll); + LL_ASSERT_DBG(conn_lll); scan->lll.conn = NULL; - LL_ASSERT(!conn_lll->link_tx_free); + LL_ASSERT_DBG(!conn_lll->link_tx_free); link = memq_deinit(&conn_lll->memq_tx.head, &conn_lll->memq_tx.tail); - LL_ASSERT(link); + LL_ASSERT_DBG(link); conn_lll->link_tx_free = link; conn = HDR_LLL2ULL(conn_lll); @@ -655,7 +655,7 @@ void ull_central_cleanup(struct node_rx_pdu *rx_free) ull_scan_is_enabled_get(SCAN_HANDLE_PHY_CODED); if (scan_coded && scan_coded != scan) { conn_lll = scan_coded->lll.conn; - LL_ASSERT(conn_lll); + LL_ASSERT_DBG(conn_lll); scan_coded->lll.conn = NULL; scan_coded->is_enabled = 0U; @@ -699,7 +699,7 @@ void ull_central_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr, * complete event. */ node = pdu_tx; - LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cc)); + LL_ASSERT_DBG(IS_PTR_ALIGNED(node, struct node_rx_cc)); /* Populate the fields required for connection complete event */ cc = node; @@ -831,8 +831,8 @@ void ull_central_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr, TICKER_USER_ID_ULL_HIGH, ticker_id_scan, ticks_at_stop, ticker_op_stop_scan_cb, scan); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_CTLR_PHY_CODED) /* Determine if coded PHY was also enabled, if so, reset the assigned @@ -853,8 +853,8 @@ void ull_central_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr, ticker_id_scan, ticker_op_stop_scan_other_cb, scan_other); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); } } #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */ @@ -880,8 +880,8 @@ void ull_central_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr, (conn->ull.ticks_slot + ticks_slot_overhead), ull_central_ticker_cb, conn, ticker_op_cb, (void *)__LINE__); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); #if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) /* enable ticker job, irrespective of disabled in this function so @@ -944,7 +944,7 @@ void ull_central_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&conn->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); /* Increment event counter. * @@ -972,7 +972,7 @@ void ull_central_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ err = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!err); + LL_ASSERT_ERR(!err); /* De-mux remaining tx nodes from FIFO */ ull_conn_tx_demux(UINT8_MAX); @@ -1044,7 +1044,7 @@ static void ticker_op_stop_scan_other_cb(uint32_t status, void *param) ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } } #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */ @@ -1053,7 +1053,7 @@ static void ticker_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); } static inline void conn_release(struct ll_scan_set *scan) @@ -1064,16 +1064,16 @@ static inline void conn_release(struct ll_scan_set *scan) memq_link_t *link; lll = scan->lll.conn; - LL_ASSERT(!lll->link_tx_free); + LL_ASSERT_DBG(!lll->link_tx_free); link = memq_deinit(&lll->memq_tx.head, &lll->memq_tx.tail); - LL_ASSERT(link); + LL_ASSERT_DBG(link); lll->link_tx_free = link; conn = HDR_LLL2ULL(lll); cc = (void *)&conn->llcp_terminate.node_rx.rx; link = cc->hdr.link; - LL_ASSERT(link); + LL_ASSERT_DBG(link); ll_rx_link_release(link); diff --git a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c index c2f86c263dff..d99896a975ba 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central_iso.c @@ -355,7 +355,7 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles) tx = cis->lll.tx.bn && cis->lll.tx.max_pdu; rx = cis->lll.rx.bn && cis->lll.rx.max_pdu; } else { - LL_ASSERT(cis->framed || iso_interval_us >= cig->c_sdu_interval); + LL_ASSERT_DBG(cis->framed || iso_interval_us >= cig->c_sdu_interval); tx = cig->c_sdu_interval && cis->c_max_sdu; rx = cig->p_sdu_interval && cis->p_max_sdu; @@ -463,7 +463,7 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles) if (!cig->central.test) { #if defined(CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY) /* TODO: Only implemented for sequential packing */ - LL_ASSERT(cig->central.packing == BT_ISO_PACKING_SEQUENTIAL); + LL_ASSERT_ERR(cig->central.packing == BT_ISO_PACKING_SEQUENTIAL); /* Use symmetric flush timeout */ cis->lll.tx.ft = DIV_ROUND_UP(total_time, iso_interval_us); @@ -494,7 +494,7 @@ uint8_t ll_cig_parameters_commit(uint8_t cig_id, uint16_t *handles) } #else - LL_ASSERT(0); + LL_ASSERT_ERR(0); #endif cis->lll.nse = DIV_ROUND_UP(se[i].total_count, cis->lll.tx.ft); } @@ -736,7 +736,7 @@ void ll_cis_create(uint16_t cis_handle, uint16_t acl_handle) /* Create access address */ err = util_aa_le32(cis->lll.access_addr); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); /* Initialize stream states */ cis->established = 0; @@ -754,7 +754,7 @@ void ll_cis_create(uint16_t cis_handle, uint16_t acl_handle) /* Initiate CIS Request Control Procedure */ if (ull_cp_cis_create(conn, cis) == BT_HCI_ERR_SUCCESS) { - LL_ASSERT(cis->group); + LL_ASSERT_DBG(cis->group); if (cis->group->state == CIG_STATE_CONFIGURABLE) { /* This CIG is now initiating an ISO connection */ @@ -859,7 +859,7 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle, /* ACL connection of the new CIS */ conn = ll_conn_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); #if defined(CONFIG_BT_CTLR_JIT_SCHEDULING) uint16_t event_counter; @@ -980,10 +980,10 @@ int ull_central_iso_cis_offset_get(uint16_t cis_handle, struct ll_conn *conn; cis = ll_conn_iso_stream_get(cis_handle); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); conn = ll_conn_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); /* `ull_conn_llcp()` (caller of this function) is called before `ull_ref_inc()` hence we do * not need to use `ull_conn_event_counter()`. @@ -1032,7 +1032,7 @@ static void cig_offset_get(struct ll_conn_iso_stream *cis) mfy.param = cis; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void mfy_cig_offset_get(void *param) @@ -1055,7 +1055,7 @@ static void mfy_cig_offset_get(void *param) */ err = ull_sched_conn_iso_free_offset_get(cig->ull.ticks_slot, &ticks_to_expire); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); /* Calculate the offset for the select CIS in the CIG */ offset_min_us = HAL_TICKER_TICKS_TO_US(ticks_to_expire) + @@ -1063,7 +1063,7 @@ static void mfy_cig_offset_get(void *param) offset_min_us += cig->sync_delay - cis->sync_delay; conn = ll_conn_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); /* Ensure the offset is not greater than the ACL interval, considering * the minimum CIS offset requirement. @@ -1088,7 +1088,7 @@ static void cis_offset_get(struct ll_conn_iso_stream *cis) mfy.param = cis; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void mfy_cis_offset_get(void *param) @@ -1161,11 +1161,11 @@ static void mfy_cis_offset_get(void *param) } success = (ret_cb == TICKER_STATUS_SUCCESS); - LL_ASSERT(success); + LL_ASSERT_ERR(success); - LL_ASSERT((ticks_current == ticks_previous) || retry--); + LL_ASSERT_ERR((ticks_current == ticks_previous) || retry--); - LL_ASSERT(id != TICKER_NULL); + LL_ASSERT_ERR(id != TICKER_NULL); } while (id != ticker_id); /* Reduced a tick for negative remainder and return positive remainder @@ -1175,7 +1175,7 @@ static void mfy_cis_offset_get(void *param) cig_remainder_us = remainder; conn = ll_conn_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); /* Add a tick for negative remainder and return positive remainder * value. diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index b68eaea19589..fb6e98915d7f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -444,7 +444,7 @@ uint8_t ll_terminate_ind_send(uint16_t handle, uint8_t reason) } else if (cis->group->state == CIG_STATE_INITIATING) { conn = ll_connected_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); /* CIS is not yet established - try to cancel procedure */ if (ull_cp_cc_cancel(conn)) { @@ -452,7 +452,7 @@ uint8_t ll_terminate_ind_send(uint16_t handle, uint8_t reason) struct node_rx_pdu *node_terminate; node_terminate = ull_pdu_rx_alloc(); - LL_ASSERT(node_terminate); + LL_ASSERT_ERR(node_terminate); node_terminate->hdr.handle = handle; node_terminate->hdr.type = NODE_RX_TYPE_TERMINATE; @@ -562,8 +562,7 @@ static bool ll_len_validate(uint16_t tx_octets, uint16_t tx_time) return true; } -uint32_t ll_length_req_send(uint16_t handle, uint16_t tx_octets, - uint16_t tx_time) +uint8_t ll_length_req_send(uint16_t handle, uint16_t tx_octets, uint16_t tx_time) { struct ll_conn *conn; @@ -601,7 +600,7 @@ void ll_length_default_get(uint16_t *max_tx_octets, uint16_t *max_tx_time) *max_tx_time = default_tx_time; } -uint32_t ll_length_default_set(uint16_t max_tx_octets, uint16_t max_tx_time) +uint8_t ll_length_default_set(uint16_t max_tx_octets, uint16_t max_tx_time) { if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK) && !ll_len_validate(max_tx_octets, max_tx_time)) { @@ -901,7 +900,7 @@ void ull_conn_setup(memq_link_t *rx_link, struct node_rx_pdu *rx) /* Setup connection in ULL disabled callback, * pass the node rx as disabled callback parameter. */ - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = rx; hdr->disabled_cb = conn_setup_adv_scan_disabled_cb; @@ -977,7 +976,7 @@ void ull_conn_rx(memq_link_t *link, struct node_rx_pdu **rx) int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy) { - LL_ASSERT(conn->lll.handle != LLL_HANDLE_INVALID); + LL_ASSERT_DBG(conn->lll.handle != LLL_HANDLE_INVALID); conn->llcp.prep.ticks_at_expire = ticks_at_expire; conn->llcp.prep.remainder = remainder; @@ -1411,9 +1410,9 @@ void ull_conn_done(struct node_rx_event_done *done) lazy, force, ticker_update_conn_op_cb, conn_ll); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY) || - ((void *)conn_ll == ull_disable_mark_get())); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY) || + ((void *)conn_ll == ull_disable_mark_get())); } } @@ -1480,7 +1479,7 @@ void ull_conn_tx_lll_enqueue(struct ll_conn *conn, uint8_t count) } link = mem_acquire(&mem_link_tx.free); - LL_ASSERT(link); + LL_ASSERT_ERR(link); /* Enqueue towards LLL */ memq_enqueue(link, tx, &conn->lll.memq_tx.tail); @@ -1543,7 +1542,7 @@ void ull_conn_lll_ack_enqueue(uint16_t handle, struct node_tx *tx) uint8_t idx; idx = MFIFO_ENQUEUE_GET(conn_ack, (void **)&lll_tx); - LL_ASSERT(lll_tx); + LL_ASSERT_ERR(lll_tx); lll_tx->handle = handle; lll_tx->node = tx; @@ -1556,13 +1555,13 @@ void ull_conn_tx_ack(uint16_t handle, memq_link_t *link, struct node_tx *tx) struct pdu_data *pdu_tx; pdu_tx = (void *)tx->pdu; - LL_ASSERT(pdu_tx->len); + LL_ASSERT_DBG(pdu_tx->len); if (pdu_tx->ll_id == PDU_DATA_LLID_CTRL) { if (handle != LLL_HANDLE_INVALID) { struct ll_conn *conn = ll_conn_get(handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); ull_cp_tx_ack(conn, tx); } @@ -1572,7 +1571,7 @@ void ull_conn_tx_ack(uint16_t handle, memq_link_t *link, struct node_tx *tx) struct ll_conn *conn; /* Tx Node not re-used, ensure link->next is non-NULL */ - LL_ASSERT(link->next); + LL_ASSERT_DBG(link->next); /* Pass conn as-is to ull_cp_release_tx(), NULL check is done there */ conn = ll_connected_get(handle); @@ -1586,12 +1585,12 @@ void ull_conn_tx_ack(uint16_t handle, memq_link_t *link, struct node_tx *tx) return; } - LL_ASSERT(!link->next); + LL_ASSERT_DBG(!link->next); } else if (handle == LLL_HANDLE_INVALID) { pdu_tx->ll_id = PDU_DATA_LLID_RESV; } else { - LL_ASSERT(handle != LLL_HANDLE_INVALID); + LL_ASSERT_DBG(handle != LLL_HANDLE_INVALID); } ll_tx_ack_put(handle, tx); @@ -1785,29 +1784,33 @@ static void ticker_update_conn_op_cb(uint32_t status, void *param) * when disconnecting or connection update (race between ticker_update * and ticker_stop calls). */ - LL_ASSERT(status == TICKER_STATUS_SUCCESS || - param == ull_update_mark_get() || - param == ull_disable_mark_get()); + LL_ASSERT_ERR((status == TICKER_STATUS_SUCCESS) || + (param == ull_update_mark_get()) || + (param == ull_disable_mark_get())); } static void ticker_stop_conn_op_cb(uint32_t status, void *param) { void *p; - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); p = ull_update_mark(param); - LL_ASSERT(p == param); + if (p != param) { + LL_ASSERT_DBG(false); + } } static void ticker_start_conn_op_cb(uint32_t status, void *param) { void *p; - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); p = ull_update_unmark(param); - LL_ASSERT(p == param); + if (p != param) { + LL_ASSERT_DBG(false); + } } static void conn_setup_adv_scan_disabled_cb(void *param) @@ -1846,7 +1849,7 @@ static void conn_setup_adv_scan_disabled_cb(void *param) #endif /* CONFIG_BT_PERIPHERAL */ default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } @@ -1857,7 +1860,7 @@ static inline void disable(uint16_t handle) int err; conn = ll_conn_get(handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); err = ull_ticker_stop_with_mark(TICKER_ID_CONN_BASE + handle, conn, &conn->lll); @@ -1910,9 +1913,9 @@ static void conn_cleanup_finalize(struct ll_conn *conn) TICKER_USER_ID_ULL_HIGH, TICKER_ID_CONN_BASE + lll->handle, ticker_stop_op_cb, conn); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY) || - ((void *)conn == ull_disable_mark_get())); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY) || + ((void *)conn == ull_disable_mark_get())); /* Invalidate the connection context */ lll->handle = LLL_HANDLE_INVALID; @@ -1969,7 +1972,7 @@ static void tx_ull_flush(struct ll_conn *conn) memq_link_t *link; link = mem_acquire(&mem_link_tx.free); - LL_ASSERT(link); + LL_ASSERT_ERR(link); /* Enqueue towards LLL */ memq_enqueue(link, tx, &conn->lll.memq_tx.tail); @@ -1988,7 +1991,7 @@ static void ticker_stop_op_cb(uint32_t status, void *param) * when disconnecting (race with ticker_stop), say on HCI Reset. */ if (status != TICKER_STATUS_SUCCESS) { - LL_ASSERT(param == ull_disable_mark_get()); + LL_ASSERT_ERR(param == ull_disable_mark_get()); return; } @@ -1997,7 +2000,7 @@ static void ticker_stop_op_cb(uint32_t status, void *param) mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void conn_disable(void *param) @@ -2018,14 +2021,14 @@ static void conn_disable(void *param) /* Setup disabled callback to be called when ref count * returns to zero. */ - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = mfy.param; hdr->disabled_cb = disabled_cb; /* Trigger LLL disable */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } else { /* No pending LLL events */ disabled_cb(&conn->lll); @@ -2041,7 +2044,7 @@ static void disabled_cb(void *param) mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void tx_lll_flush(void *param) @@ -2067,7 +2070,7 @@ static void tx_lll_flush(void *param) struct lll_tx *tx_buf; idx = MFIFO_ENQUEUE_GET(conn_ack, (void **)&tx_buf); - LL_ASSERT(tx_buf); + LL_ASSERT_ERR(tx_buf); tx_buf->handle = LLL_HANDLE_INVALID; tx_buf->node = tx; @@ -2087,7 +2090,7 @@ static void tx_lll_flush(void *param) * populated before this mayfly function was scheduled. */ rx = (void *)&conn->llcp_terminate.node_rx; - LL_ASSERT(rx->hdr.link); + LL_ASSERT_DBG(rx->hdr.link); link = rx->hdr.link; rx->hdr.link = NULL; @@ -2240,8 +2243,8 @@ static void ull_conn_update_ticker(struct ll_conn *conn, uint32_t ticker_status = ticker_stop_abs(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, ticker_id_conn, ticks_at_expire, ticker_stop_conn_op_cb, (void *)conn); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); ticker_status = ticker_start( TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, ticker_id_conn, ticks_at_expire, ticks_win_offset, HAL_TICKER_US_TO_TICKS(periodic_us), @@ -2261,8 +2264,8 @@ static void ull_conn_update_ticker(struct ll_conn *conn, ull_central_ticker_cb, #endif /* CONFIG_BT_PERIPHERAL && CONFIG_BT_CENTRAL */ conn, ticker_start_conn_op_cb, (void *)conn); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); #if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) /* enable ticker job, if disabled in this function */ @@ -2464,7 +2467,7 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_ #endif /*CONFIG_BT_CENTRAL */ default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -2826,7 +2829,7 @@ static uint32_t get_ticker_offset(uint8_t ticker_id, uint16_t *lazy) } } - LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(ret_cb == TICKER_STATUS_SUCCESS); /* Reduced a tick for negative remainder and return positive remainder * value. @@ -2868,7 +2871,7 @@ static void mfy_past_sender_offset_get(void *param) if (adv_sync_handle != BT_HCI_ADV_HANDLE_INVALID) { const struct ll_adv_sync_set *adv_sync = ull_adv_sync_get(adv_sync_handle); - LL_ASSERT(adv_sync); + LL_ASSERT_DBG(adv_sync); ticker_offset_us = get_ticker_offset(TICKER_ID_ADV_SYNC_BASE + adv_sync_handle, &lazy); @@ -2880,7 +2883,7 @@ static void mfy_past_sender_offset_get(void *param) uint32_t interval_us = sync->interval * PERIODIC_INT_UNIT_US; uint32_t window_widening_event_us; - LL_ASSERT(sync); + LL_ASSERT_DBG(sync); ticker_offset_us = get_ticker_offset(TICKER_ID_SCAN_SYNC_BASE + sync_handle, &lazy); @@ -2924,7 +2927,7 @@ void ull_conn_past_sender_offset_request(struct ll_conn *conn) mfy.param = conn; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } #endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c index a28655218738..30dcb8419ad7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c @@ -460,7 +460,7 @@ void ull_conn_iso_done(struct node_rx_event_done *done) /* Check all CISes for supervison/establishment timeout */ for (cis_idx = 0; cis_idx < cig->lll.num_cis; cis_idx++) { cis = ll_conn_iso_stream_get_by_group(cig, &handle_iter); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); if (cis->lll.active && cis->lll.handle != LLL_HANDLE_INVALID) { /* CIS was setup and is now expected to be going */ @@ -485,7 +485,7 @@ void ull_conn_iso_done(struct node_rx_event_done *done) if (!cis->event_expire) { struct ll_conn *conn = ll_conn_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); cis->event_expire = RADIO_CONN_EVENTS( conn->supervision_timeout * 10U * 1000U, @@ -532,7 +532,7 @@ void ull_conn_iso_done(struct node_rx_event_done *done) struct ll_conn *conn; conn = ll_connected_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); ticker_status = ticker_update(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, @@ -543,9 +543,9 @@ void ull_conn_iso_done(struct node_rx_event_done *done) ticker_update_cig_op_cb, cig); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY) || - ((void *)conn == ull_disable_mark_get())); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY) || + ((void *)conn == ull_disable_mark_get())); } } @@ -569,8 +569,8 @@ void ull_conn_iso_cis_stop(struct ll_conn_iso_stream *cis, if (cis->teardown) { /* Teardown already started */ - LL_ASSERT(!cis->released_cb || !cis_released_cb || - (cis->released_cb == cis_released_cb)); + LL_ASSERT_ERR(!cis->released_cb || !cis_released_cb || + (cis->released_cb == cis_released_cb)); if (cis_released_cb) { cis->released_cb = cis_released_cb; @@ -600,15 +600,15 @@ void ull_conn_iso_cis_stop(struct ll_conn_iso_stream *cis, * continue CIS teardown from there. The disabled_cb cannot be * reserved for other use. */ - LL_ASSERT(!hdr->disabled_cb || - (hdr->disabled_cb == cis_disabled_cb)); + LL_ASSERT_ERR(!hdr->disabled_cb || + (hdr->disabled_cb == cis_disabled_cb)); hdr->disabled_param = mfy.param; hdr->disabled_cb = cis_disabled_cb; /* Trigger LLL disable */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } else { /* No pending LLL events */ @@ -707,7 +707,7 @@ void ull_conn_iso_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment CIS event counters */ for (int i = 0; i < cig->lll.num_cis; i++) { cis = ll_conn_iso_stream_get_by_group(cig, &handle_iter); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); /* New CIS may become available by creation prior to the CIG * event in which it has event_count == 0. Don't increment @@ -747,7 +747,7 @@ void ull_conn_iso_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&cig->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); /* Append timing parameters */ p.ticks_at_expire = ticks_at_expire; @@ -767,7 +767,7 @@ void ull_conn_iso_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, mfy.fp = lll_peripheral_iso_prepare; #else /* !CONFIG_BT_CTLR_CENTRAL_ISO && !CONFIG_BT_CTLR_PERIPHERAL_ISO */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); return; #endif /* !CONFIG_BT_CTLR_CENTRAL_ISO && !CONFIG_BT_CTLR_PERIPHERAL_ISO */ @@ -791,7 +791,7 @@ void ull_conn_iso_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ err = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!err); + LL_ASSERT_ERR(!err); /* Handle ISO Transmit Test for this CIG */ ull_conn_iso_transmit_test_cig_interval(cig->lll.handle, ticks_at_expire); @@ -979,6 +979,17 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle, lost_cig_events = 1U; cis_offset = cis->offset + iso_interval_us - acl_latency_us; } + /* Correct the cis_offset to next CIG event, if the ACL and CIG overlaps. + * ACL radio event at the instant was skipped and a relative CIS offset at + * the current ACL event has been calculated. But the current ACL event + * is partially overlapping with the other of CISes (not yet established) in + * the CIG event. Hence, lets establish the CIS at the next ISO interval so + * as to have a positive CIG event offset. + */ + if (cis_offset < (cig->sync_delay - cis->sync_delay)) { + cis_offset += iso_interval_us; + lost_cig_events++; + } cis->lll.event_count_prepare += lost_cig_events; @@ -1022,9 +1033,9 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle, /* FIXME: Handle latency due to skipped ACL events around the * instant to start CIG */ - LL_ASSERT(instant_latency == 0U); + LL_ASSERT_ERR(instant_latency == 0U); } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); return; } @@ -1032,7 +1043,7 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle, /* Make sure we have time to service first subevent. TODO: Improve * by skipping interval(s) and incrementing event_count. */ - LL_ASSERT(cig_offset_us > 0); + LL_ASSERT_ERR(cig_offset_us > 0); ull_hdr_init(&cig->ull); @@ -1097,8 +1108,8 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle, TICKER_NULL_LAZY, ticks_slot, ull_conn_iso_ticker_cb, cig, ticker_start_op_cb, NULL); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); /* Set CIG and the first CIS state as active */ cig->state = CIG_STATE_ACTIVE; @@ -1114,7 +1125,7 @@ static void cis_lazy_fill(struct ll_conn_iso_stream *cis) mfy.param = cis; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void mfy_cis_lazy_fill(void *param) @@ -1177,11 +1188,11 @@ static void mfy_cis_lazy_fill(void *param) } success = (ret_cb == TICKER_STATUS_SUCCESS); - LL_ASSERT(success); + LL_ASSERT_ERR(success); - LL_ASSERT((ticks_current == ticks_previous) || retry--); + LL_ASSERT_ERR((ticks_current == ticks_previous) || retry--); - LL_ASSERT(id != TICKER_NULL); + LL_ASSERT_ERR(id != TICKER_NULL); } while (id != ticker_id); /* Set CIS active in already active CIG and any previous laziness in @@ -1203,7 +1214,7 @@ static void ticker_start_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); } static void ticker_update_cig_op_cb(uint32_t status, void *param) @@ -1212,9 +1223,9 @@ static void ticker_update_cig_op_cb(uint32_t status, void *param) * when disconnecting (race between ticker_update and ticker_stop * calls). TODO: Are the race-checks needed? */ - LL_ASSERT(status == TICKER_STATUS_SUCCESS || - param == ull_update_mark_get() || - param == ull_disable_mark_get()); + LL_ASSERT_ERR((status == TICKER_STATUS_SUCCESS) || + (param == ull_update_mark_get()) || + (param == ull_disable_mark_get())); } static void cis_disabled_cb(void *param) @@ -1241,7 +1252,7 @@ static void cis_disabled_cb(void *param) num_cis = cig->lll.num_cis; for (cis_idx = 0; cis_idx < num_cis; cis_idx++) { cis = ll_conn_iso_stream_get_by_group(cig, &handle_iter); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); if (!cis->lll.active && (cis->lll.flush != LLL_CIS_FLUSH_COMPLETE)) { /* CIS is not active and did not just complete LLL flush - skip it */ @@ -1257,7 +1268,7 @@ static void cis_disabled_cb(void *param) ll_iso_stream_released_cb_t cis_released_cb; conn = ll_conn_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); cis_released_cb = cis->released_cb; cis->released_cb = NULL; @@ -1285,7 +1296,7 @@ static void cis_disabled_cb(void *param) cis->lll.acl_handle = LLL_HANDLE_INVALID; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } /* CIS is no longer active */ @@ -1313,7 +1324,7 @@ static void cis_disabled_cb(void *param) * further enqueuing of TX nodes for terminating CIS. */ node_terminate = ull_pdu_rx_alloc(); - LL_ASSERT(node_terminate); + LL_ASSERT_ERR(node_terminate); node_terminate->hdr.handle = cis->lll.handle; node_terminate->hdr.type = NODE_RX_TYPE_TERMINATE; *((uint8_t *)node_terminate->pdu) = cis->terminate_reason; @@ -1321,7 +1332,7 @@ static void cis_disabled_cb(void *param) ll_rx_put_sched(node_terminate->hdr.link, node_terminate); } else { conn = ll_conn_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); /* CIS was not established - complete the procedure with error */ if (ull_cp_cc_awaiting_established(conn)) { @@ -1369,8 +1380,8 @@ static void cis_disabled_cb(void *param) ticker_stop_op_cb, cig); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); } } @@ -1395,7 +1406,7 @@ static void cis_tx_lll_flush(void *param) memq_link_t *link; cis = ll_conn_iso_stream_get_by_group(cig, &handle_iter); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); lll = &cis->lll; @@ -1423,9 +1434,9 @@ static void cis_tx_lll_flush(void *param) (void **)&tx); } - LL_ASSERT(!lll->link_tx_free); + LL_ASSERT_DBG(!lll->link_tx_free); link = memq_deinit(&lll->memq_tx.head, &lll->memq_tx.tail); - LL_ASSERT(link); + LL_ASSERT_DBG(link); lll->link_tx_free = link; lll->flush = LLL_CIS_FLUSH_COMPLETE; @@ -1444,13 +1455,13 @@ static void ticker_stop_op_cb(uint32_t status, void *param) uint32_t ret; /* Assert if race between thread and ULL */ - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); /* Check if any pending LLL events that need to be aborted */ mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void cig_disable(void *param) @@ -1471,14 +1482,14 @@ static void cig_disable(void *param) /* Setup disabled callback to be called when ref count * returns to zero. */ - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = mfy.param; hdr->disabled_cb = cig_disabled_cb; /* Trigger LLL disable */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } else { /* No pending LLL events */ cig_disabled_cb(&cig->lll); @@ -1527,7 +1538,7 @@ void ull_conn_iso_transmit_test_cig_interval(uint16_t handle, uint32_t ticks_at_ uint8_t tx_sdu_count; cig = ll_conn_iso_group_get(handle); - LL_ASSERT(cig); + LL_ASSERT_DBG(cig); handle_iter = UINT16_MAX; @@ -1540,7 +1551,7 @@ void ull_conn_iso_transmit_test_cig_interval(uint16_t handle, uint32_t ticks_at_ sdu_interval = cig->c_sdu_interval; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); return; } @@ -1550,7 +1561,7 @@ void ull_conn_iso_transmit_test_cig_interval(uint16_t handle, uint32_t ticks_at_ /* Handle ISO Transmit Test for all active CISes in the group */ for (uint8_t i = 0; i < cig->lll.num_cis; i++) { cis = ll_conn_iso_stream_get_by_group(cig, &handle_iter); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); if (!cis->hdr.test_mode.tx.enabled || cis->lll.handle == LLL_HANDLE_INVALID) { continue; diff --git a/subsys/bluetooth/controller/ll_sw/ull_df.c b/subsys/bluetooth/controller/ll_sw/ull_df.c index ba04dac16489..ac26c11cd725 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_df.c +++ b/subsys/bluetooth/controller/ll_sw/ull_df.c @@ -451,7 +451,7 @@ uint8_t ll_df_set_cl_iq_sampling_enable(uint16_t handle, #if defined(CONFIG_BT_CTLR_DF_DEBUG_ENABLE) /* When CTE is enabled there should be no iq report allocated */ - IF_SINGLE_ADV_SYNC_SET(LL_ASSERT(iq_report_alloc_count == 0)); + IF_SINGLE_ADV_SYNC_SET(LL_ASSERT_DBG(iq_report_alloc_count == 0)); #endif /* CONFIG_BT_CTLR_DF_DEBUG_ENABLE */ /* Enable of already enabled CTE updates AoA configuration */ @@ -510,7 +510,7 @@ uint8_t ll_df_set_cl_iq_sampling_enable(uint16_t handle, * Periodic sync lost event also disables the CTE sampling. */ err = ull_sync_slot_update(sync, slot_plus_us, slot_minus_us); - LL_ASSERT(err == 0 || err == -ENOENT); + LL_ASSERT_DBG(err == 0 || err == -ENOENT); } return 0; @@ -580,7 +580,7 @@ void ull_df_iq_report_mem_release(struct node_rx_pdu *rx) void ull_iq_report_link_inc_quota(int8_t delta) { - LL_ASSERT(delta <= 0 || mem_link_iq_report_quota_pdu < (IQ_REPORT_CNT)); + LL_ASSERT_DBG(delta <= 0 || mem_link_iq_report_quota_pdu < (IQ_REPORT_CNT)); mem_link_iq_report_quota_pdu += delta; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_filter.c b/subsys/bluetooth/controller/ll_sw/ull_filter.c index bff2a0633674..8466e20731e9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_filter.c +++ b/subsys/bluetooth/controller/ll_sw/ull_filter.c @@ -277,8 +277,8 @@ uint8_t ll_fal_remove(bt_addr_le_t *addr) #if defined(CONFIG_BT_CTLR_PRIVACY) void ll_rl_id_addr_get(uint8_t rl_idx, uint8_t *id_addr_type, uint8_t *id_addr) { - LL_ASSERT(rl_idx < CONFIG_BT_CTLR_RL_SIZE); - LL_ASSERT(rl[rl_idx].taken); + LL_ASSERT_DBG(rl_idx < CONFIG_BT_CTLR_RL_SIZE); + LL_ASSERT_DBG(rl[rl_idx].taken); *id_addr_type = rl[rl_idx].id_addr_type; (void)memcpy(id_addr, rl[rl_idx].id_addr.val, BDADDR_SIZE); @@ -607,7 +607,7 @@ bool ull_filter_ull_pal_listed(const uint8_t rl_idx, uint8_t *const addr_type, return false; } - LL_ASSERT(rl[rl_idx].taken); + LL_ASSERT_DBG(rl[rl_idx].taken); if (rl[rl_idx].pal) { uint8_t pal_idx = rl[rl_idx].pal - 1; @@ -663,7 +663,7 @@ struct lll_filter *ull_filter_lll_get(bool filter) } return &rl_filter; #else - LL_ASSERT(filter); + LL_ASSERT_DBG(filter); return &fal_filter; #endif } @@ -752,7 +752,7 @@ void ull_filter_rpa_update(bool timeout) sys_memcpy_swap(irk, peer_irks[rl[i].pirk_idx], IRK_SIZE); err = bt_rpa_create(irk, &rl[i].peer_rpa); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); #if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY) /* a new key was added, * invalidate the known/unknown peer RPA cache @@ -766,7 +766,7 @@ void ull_filter_rpa_update(bool timeout) bt_addr_t rpa; err = bt_rpa_create(rl[i].local_irk, &rpa); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); /* pointer read/write assumed to be atomic * so that if ISR fires the local_rpa pointer * will always point to a valid full RPA @@ -805,7 +805,7 @@ const uint8_t *ull_filter_adva_get(uint8_t rl_idx) { /* AdvA */ if (rl_idx < ARRAY_SIZE(rl) && rl[rl_idx].lirk) { - LL_ASSERT(rl[rl_idx].rpas_ready); + LL_ASSERT_DBG(rl[rl_idx].rpas_ready); return rl[rl_idx].local_rpa->val; } @@ -884,13 +884,13 @@ uint8_t ull_filter_lll_rl_idx(bool filter, uint8_t devmatch_id) uint8_t i; if (filter) { - LL_ASSERT(devmatch_id < ARRAY_SIZE(fal)); - LL_ASSERT(fal[devmatch_id].taken); + LL_ASSERT_DBG(devmatch_id < ARRAY_SIZE(fal)); + LL_ASSERT_DBG(fal[devmatch_id].taken); i = fal[devmatch_id].rl_idx; } else { - LL_ASSERT(devmatch_id < ARRAY_SIZE(rl)); + LL_ASSERT_DBG(devmatch_id < ARRAY_SIZE(rl)); i = devmatch_id; - LL_ASSERT(rl[i].taken); + LL_ASSERT_DBG(rl[i].taken); } return i; @@ -900,10 +900,10 @@ uint8_t ull_filter_lll_rl_irk_idx(uint8_t irkmatch_id) { uint8_t i; - LL_ASSERT(irkmatch_id < peer_irk_count); + LL_ASSERT_DBG(irkmatch_id < peer_irk_count); i = peer_irk_rl_ids[irkmatch_id]; - LL_ASSERT(i < CONFIG_BT_CTLR_RL_SIZE); - LL_ASSERT(rl[i].taken); + LL_ASSERT_DBG(i < CONFIG_BT_CTLR_RL_SIZE); + LL_ASSERT_DBG(rl[i].taken); return i; } @@ -914,7 +914,7 @@ bool ull_filter_lll_irk_in_fal(uint8_t rl_idx) return false; } - LL_ASSERT(rl[rl_idx].taken); + LL_ASSERT_DBG(rl[rl_idx].taken); return rl[rl_idx].fal; } @@ -938,8 +938,8 @@ bool ull_filter_lll_rl_idx_allowed(uint8_t irkmatch_ok, uint8_t rl_idx) return true; } - LL_ASSERT(rl_idx < CONFIG_BT_CTLR_RL_SIZE); - LL_ASSERT(rl[rl_idx].taken); + LL_ASSERT_DBG(rl_idx < CONFIG_BT_CTLR_RL_SIZE); + LL_ASSERT_DBG(rl[rl_idx].taken); return !rl[rl_idx].pirk || rl[rl_idx].dev; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_iso.c b/subsys/bluetooth/controller/ll_sw/ull_iso.c index 31a51a8bc145..c32aaced2076 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_iso.c @@ -662,7 +662,7 @@ static isoal_status_t ll_iso_test_sdu_alloc(const struct isoal_sink *sink_ctx, struct ll_conn_iso_stream *cis; cis = ll_iso_stream_connected_get(sink_ctx->session.handle); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); /* For unframed, SDU counter is the payload number */ cis->hdr.test_mode.rx.sdu_counter = @@ -675,7 +675,7 @@ static isoal_status_t ll_iso_test_sdu_alloc(const struct isoal_sink *sink_ctx, stream_handle = LL_BIS_SYNC_IDX_FROM_HANDLE(handle); sync_stream = ull_sync_iso_stream_get(stream_handle); - LL_ASSERT(sync_stream); + LL_ASSERT_DBG(sync_stream); sync_stream->test_mode->sdu_counter = (uint32_t)valid_pdu->meta->payload_number; @@ -709,7 +709,7 @@ static isoal_status_t ll_iso_test_sdu_emit(const struct isoal_sink * struct ll_conn_iso_stream *cis; cis = ll_iso_stream_connected_get(sink_ctx->session.handle); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); test_mode_rx = &cis->hdr.test_mode.rx; max_sdu = cis->c_max_sdu; @@ -721,7 +721,7 @@ static isoal_status_t ll_iso_test_sdu_emit(const struct isoal_sink * stream_handle = LL_BIS_SYNC_IDX_FROM_HANDLE(handle); sync_stream = ull_sync_iso_stream_get(stream_handle); - LL_ASSERT(sync_stream); + LL_ASSERT_DBG(sync_stream); sync_iso = ull_sync_iso_by_stream_get(stream_handle); @@ -790,7 +790,7 @@ static isoal_status_t ll_iso_test_sdu_emit(const struct isoal_sink * break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); return ISOAL_STATUS_ERR_SDU_EMIT; } break; @@ -1105,7 +1105,7 @@ void ll_iso_transmit_test_send_sdu(uint16_t handle, uint32_t ticks_at_expire) uint8_t rand_8; cis = ll_iso_stream_connected_get(handle); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); if (!cis->hdr.test_mode.tx.enabled) { /* Transmit Test Mode not enabled */ @@ -1130,12 +1130,12 @@ void ll_iso_transmit_test_send_sdu(uint16_t handle, uint32_t ticks_at_expire) break; case BT_HCI_ISO_TEST_MAX_SIZE_SDU: - LL_ASSERT(max_sdu > ISO_TEST_PACKET_COUNTER_SIZE); + LL_ASSERT_DBG(max_sdu > ISO_TEST_PACKET_COUNTER_SIZE); remaining_tx = max_sdu; break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); return; } @@ -1206,7 +1206,7 @@ void ll_iso_transmit_test_send_sdu(uint16_t handle, uint32_t ticks_at_expire) /* Send to ISOAL */ err = isoal_tx_sdu_fragment(source_handle, &sdu); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); remaining_tx -= sdu.size; @@ -1222,7 +1222,7 @@ void ll_iso_transmit_test_send_sdu(uint16_t handle, uint32_t ticks_at_expire) } else if (IS_ADV_ISO_HANDLE(handle)) { /* FIXME: Implement for broadcaster */ } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } #endif /* CONFIG_BT_CTLR_CONN_ISO */ @@ -1503,7 +1503,7 @@ void ull_iso_lll_ack_enqueue(uint16_t handle, struct node_tx_iso *node_tx) ll_tx_ack_put(handle, (void *)node_tx); ll_rx_sched(); } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -1538,7 +1538,7 @@ void ull_iso_lll_event_prepare(uint16_t handle, uint64_t event_count) isoal_tx_event_prepare(dp->source_hdl, event_count); } } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */ @@ -1692,7 +1692,7 @@ static void iso_rx_demux(void *param) const isoal_status_t err = isoal_rx_pdu_recombine(dp->sink_hdl, &pckt_meta); - LL_ASSERT(err == ISOAL_STATUS_OK); /* TODO handle err */ + LL_ASSERT_ERR(err == ISOAL_STATUS_OK); /* TODO handle err */ } #endif /* CONFIG_BT_CTLR_CONN_ISO || CONFIG_BT_CTLR_SYNC_ISO */ @@ -1702,7 +1702,7 @@ static void iso_rx_demux(void *param) break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } @@ -1749,7 +1749,7 @@ void ll_iso_rx_dequeue(void) link = memq_dequeue(memq_ll_iso_rx.tail, &memq_ll_iso_rx.head, (void **)&rx); - LL_ASSERT(link); + LL_ASSERT_DBG(link); mem_release(link, &mem_link_iso_rx.free); @@ -1758,7 +1758,7 @@ void ll_iso_rx_dequeue(void) case NODE_RX_TYPE_ISO_PDU: break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } @@ -1825,7 +1825,7 @@ static isoal_status_t ll_iso_pdu_alloc(struct isoal_pdu_buffer *pdu_buffer) /* TODO: Report overflow to HCI and remove assert * data_buf_overflow(evt, BT_OVERFLOW_LINK_ISO) */ - LL_ASSERT(0); + LL_ASSERT_ERR(0); return ISOAL_STATUS_ERR_PDU_ALLOC; } @@ -1860,9 +1860,9 @@ static isoal_status_t ll_iso_pdu_write(struct isoal_pdu_buffer *pdu_buffer, ARG_UNUSED(pdu_offset); ARG_UNUSED(consume_len); - LL_ASSERT(pdu_buffer); - LL_ASSERT(pdu_buffer->pdu); - LL_ASSERT(sdu_payload); + LL_ASSERT_DBG(pdu_buffer); + LL_ASSERT_DBG(pdu_buffer->pdu); + LL_ASSERT_DBG(sdu_payload); if ((pdu_offset + consume_len) > pdu_buffer->size) { /* Exceeded PDU buffer */ @@ -1887,7 +1887,7 @@ static isoal_status_t ll_iso_pdu_emit(struct node_tx_iso *node_tx, memq_link_t *link; link = mem_acquire(&mem_link_iso_tx.free); - LL_ASSERT(link); + LL_ASSERT_ERR(link); if (ll_iso_tx_mem_enqueue(handle, node_tx, link)) { return ISOAL_STATUS_ERR_PDU_EMIT; @@ -1947,7 +1947,7 @@ static int init_reset(void) /* Acquire a link to initialize ull rx memq */ link = mem_acquire(&mem_link_iso_rx.free); - LL_ASSERT(link); + LL_ASSERT_DBG(link); #if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH) /* Initialize ull rx memq */ @@ -1956,7 +1956,7 @@ static int init_reset(void) /* Acquire a link to initialize ll_iso_rx memq */ link = mem_acquire(&mem_link_iso_rx.free); - LL_ASSERT(link); + LL_ASSERT_DBG(link); /* Initialize ll_iso_rx memq */ MEMQ_INIT(ll_iso_rx, link); @@ -2012,7 +2012,7 @@ void ull_iso_resume_ticker_start(struct lll_event *resume_event, ticker_id = TICKER_ID_SCAN_SYNC_ISO_RESUME_BASE + group_handle; #endif /* CONFIG_BT_CTLR_SYNC_ISO */ } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } if (role == BT_HCI_ROLE_PERIPHERAL) { @@ -2031,7 +2031,7 @@ void ull_iso_resume_ticker_start(struct lll_event *resume_event, cis = ll_conn_iso_stream_get(stream_handle); conn = ll_conn_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); phy = conn->lll.phy_rx; #endif /* CONFIG_BT_CTLR_CONN_ISO */ @@ -2045,7 +2045,7 @@ void ull_iso_resume_ticker_start(struct lll_event *resume_event, phy = sync_iso->lll.phy; #endif /* CONFIG_BT_CTLR_SYNC_ISO */ } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); } resume_delay_us += @@ -2058,7 +2058,7 @@ void ull_iso_resume_ticker_start(struct lll_event *resume_event, } resume_offset_us = (int32_t)(resume_timeout - resume_delay_us); - LL_ASSERT(resume_offset_us >= 0); + LL_ASSERT_DBG(resume_offset_us >= 0); /* Setup resume timeout as single-shot */ ret = ticker_start(TICKER_INSTANCE_ID_CTLR, @@ -2073,15 +2073,15 @@ void ull_iso_resume_ticker_start(struct lll_event *resume_event, ticker_resume_cb, resume_event, ticker_resume_op_cb, NULL); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } static void ticker_resume_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); } static void ticker_resume_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, @@ -2094,7 +2094,7 @@ static void ticker_resume_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint32_t ret; ARG_UNUSED(ticks_drift); - LL_ASSERT(lazy == 0); + LL_ASSERT_DBG(lazy == 0); resume_event = param; @@ -2109,6 +2109,6 @@ static void ticker_resume_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } #endif /* CONFIG_BT_CTLR_CONN_ISO || CONFIG_BT_CTLR_SYNC_ISO */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp.c b/subsys/bluetooth/controller/ll_sw/ull_llcp.c index 0f9877ecc845..f23b7f388bc2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp.c @@ -109,7 +109,7 @@ static struct proc_ctx *proc_ctx_acquire(struct llcp_mem_pool *owner) void llcp_proc_ctx_release(struct proc_ctx *ctx) { /* We need to have an owner otherwise the memory allocated would leak */ - LL_ASSERT(ctx->owner); + LL_ASSERT_DBG(ctx->owner); /* Release the memory back to the owner */ mem_release(ctx, &ctx->owner->free); @@ -297,7 +297,7 @@ void llcp_tx_resume_data(struct ll_conn *conn, enum llcp_tx_q_pause_data_mask re void llcp_rx_node_retain(struct proc_ctx *ctx) { - LL_ASSERT(ctx->node_ref.rx); + LL_ASSERT_DBG(ctx->node_ref.rx); /* Only retain if not already retained */ if (ctx->node_ref.rx->hdr.type != NODE_RX_TYPE_RETAIN) { @@ -311,7 +311,7 @@ void llcp_rx_node_retain(struct proc_ctx *ctx) void llcp_rx_node_release(struct proc_ctx *ctx) { - LL_ASSERT(ctx->node_ref.rx); + LL_ASSERT_DBG(ctx->node_ref.rx); /* Only release if retained */ if (ctx->node_ref.rx->hdr.type == NODE_RX_TYPE_RETAIN) { @@ -472,7 +472,7 @@ void ull_cp_release_tx(struct ll_conn *conn, struct node_tx *tx) { #if defined(LLCP_TX_CTRL_BUF_QUEUE_ENABLE) if (conn) { - LL_ASSERT(conn->llcp.tx_buffer_alloc > 0); + LL_ASSERT_DBG(conn->llcp.tx_buffer_alloc > 0); if (conn->llcp.tx_buffer_alloc > CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM) { common_tx_buffer_alloc--; } @@ -511,7 +511,7 @@ int ull_cp_prt_elapse(struct ll_conn *conn, uint16_t elapsed_event, uint8_t *err struct proc_ctx *ctx; ctx = llcp_lr_peek(conn); - LL_ASSERT(ctx); + LL_ASSERT_DBG(ctx); if (ctx->proc == PROC_TERMINATE) { /* Active procedure is ACL Termination */ @@ -1026,7 +1026,7 @@ uint8_t ull_cp_conn_update(struct ll_conn *conn, uint16_t interval_min, uint16_t } #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ } else { - LL_ASSERT(0); /* Unknown procedure */ + LL_ASSERT_DBG(0); /* Unknown procedure */ } llcp_lr_enqueue(conn, ctx); @@ -1051,7 +1051,7 @@ uint8_t ull_cp_periodic_sync(struct ll_conn *conn, struct ll_sync_set *sync, uint8_t phy; /* Exactly one of the sync and adv_sync pointers should be non-null */ - LL_ASSERT((!adv_sync && sync) || (adv_sync && !sync)); + LL_ASSERT_DBG((!adv_sync && sync) || (adv_sync && !sync)); if (!feature_peer_periodic_sync_recv(conn)) { return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE; @@ -1080,7 +1080,7 @@ uint8_t ull_cp_periodic_sync(struct ll_conn *conn, struct ll_sync_set *sync, rl_idx = ull_filter_rl_find(addr_type, sync->peer_id_addr, NULL); /* A resolved address must be present in the resolve list */ - LL_ASSERT(rl_idx < ll_rl_size_get()); + LL_ASSERT_DBG(rl_idx < ll_rl_size_get()); /* Generate RPAs if required */ ull_filter_rpa_update(false); @@ -1999,7 +1999,7 @@ void ull_cp_rx(struct ll_conn *conn, memq_link_t *link, struct node_rx_pdu *rx) */ /* Process PDU as a new remote request */ - LL_ASSERT(pdu_valid); + LL_ASSERT_DBG(pdu_valid); llcp_rr_new(conn, link, rx, true); } else { /* Local active procedure diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c index 6e12571d88c6..e70d6e664fc9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c @@ -65,7 +65,7 @@ static void cc_ntf_established(struct ll_conn *conn, struct proc_ctx *ctx) /* Allocate ntf node */ ntf = ctx->node_ref.rx; - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); ctx->node_ref.rx = NULL; piggy_back = (ntf->hdr.type != NODE_RX_TYPE_RETAIN); @@ -146,7 +146,7 @@ static void llcp_rp_cc_tx_rsp(struct ll_conn *conn, struct proc_ctx *ctx) /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; conn_event_count = ctx->data.cis_create.conn_event_count; @@ -201,7 +201,7 @@ static void llcp_rp_cc_tx_reject(struct ll_conn *conn, struct proc_ctx *ctx, uin /* Allocate tx node */ tx = ctx->node_ref.tx; - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); ctx->node_ref.tx = NULL; pdu = (struct pdu_data *)tx->pdu; @@ -221,7 +221,7 @@ static void rp_cc_ntf_create(struct ll_conn *conn, struct proc_ctx *ctx) ntf = ctx->node_ref.rx; ctx->node_ref.rx = NULL; - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); ntf->hdr.type = NODE_RX_TYPE_CIS_REQUEST; ntf->hdr.handle = conn->lll.handle; @@ -490,7 +490,7 @@ static void rp_cc_state_wait_rx_cis_ind(struct ll_conn *conn, struct proc_ctx *c } /* If we get to here the CIG_ID referred in req/acquire has become void/invalid */ /* This cannot happen unless the universe has started to deflate */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); case RP_CC_EVT_REJECT: /* Handle CIS creation rejection */ break; @@ -656,7 +656,7 @@ static void rp_cc_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_ break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -767,7 +767,7 @@ static void lp_cc_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode) /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; @@ -781,7 +781,7 @@ static void lp_cc_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode) break; default: /* Unknown opcode */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -929,7 +929,7 @@ static void lp_cc_st_idle(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t ev break; default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } break; @@ -971,7 +971,7 @@ static void cc_prepare_cis_ind(struct ll_conn *conn, struct proc_ctx *ctx) &ctx->data.cis_create.cis_offset_max, &ctx->data.cis_create.conn_event_count, ctx->data.cis_create.aa); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); ctx->state = LP_CC_STATE_WAIT_INSTANT; ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_UNUSED; @@ -1054,7 +1054,7 @@ static void lp_cc_st_wait_rx_cis_rsp_cancel(struct ll_conn *conn, struct proc_ct case LP_CC_EVT_CIS_RSP: /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; @@ -1177,7 +1177,7 @@ static void lp_cc_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_ break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c index 04b51ce79947..772aba812d15 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c @@ -89,7 +89,7 @@ static void lp_chmu_tx(struct ll_conn *conn, struct proc_ctx *ctx) /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; @@ -180,7 +180,7 @@ static void lp_chmu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -293,7 +293,7 @@ static void rp_chmu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index b0e28e124bdc..84098f1b149f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -159,7 +159,7 @@ static void lp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; @@ -218,7 +218,7 @@ static void lp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) #endif /* CONFIG_BT_CTLR_SCA_UPDATE */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } ctx->tx_opcode = pdu->llctrl.opcode; @@ -255,7 +255,7 @@ static void lp_comm_ntf_feature_exchange(struct ll_conn *conn, struct proc_ctx * break; default: /* Unexpected PDU, should not get through, so ASSERT */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -268,7 +268,7 @@ static void lp_comm_ntf_version_ind(struct ll_conn *conn, struct proc_ctx *ctx, break; default: /* Unexpected PDU, should not get through, so ASSERT */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -305,7 +305,7 @@ static void lp_comm_ntf_cte_req(struct ll_conn *conn, struct proc_ctx *ctx, stru break; default: /* Unexpected PDU, should not get through, so ASSERT */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -393,7 +393,7 @@ static void lp_comm_ntf(struct ll_conn *conn, struct proc_ctx *ctx) if (!ntf) { /* Allocate ntf node */ ntf = llcp_ntf_alloc(); - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); piggy_back = 0U; } @@ -424,7 +424,7 @@ static void lp_comm_ntf(struct ll_conn *conn, struct proc_ctx *ctx) break; #endif /* CONFIG_BT_CTLR_SCA_UPDATE */ default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -585,7 +585,7 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t #endif /* CONFIG_BT_CTLR_SCA_UPDATE */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -716,7 +716,7 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t #endif /* CONFIG_BT_CTLR_SCA_UPDATE */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -819,7 +819,7 @@ static void lp_comm_rx_decode(struct ll_conn *conn, struct proc_ctx *ctx, struct break; case PDU_DATA_LLCTRL_TYPE_TERMINATE_IND: /* No response expected */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; #if defined(CONFIG_BT_CTLR_DATA_LENGTH) case PDU_DATA_LLCTRL_TYPE_LENGTH_RSP: @@ -844,7 +844,7 @@ static void lp_comm_rx_decode(struct ll_conn *conn, struct proc_ctx *ctx, struct break; default: /* Unknown opcode */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -889,7 +889,7 @@ static void lp_comm_st_wait_ntf_avail(struct ll_conn *conn, struct proc_ctx *ctx * out of the ones handled in ull_llcp_common should end up waiting for * non-piggy-back'ed NTF */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } break; @@ -919,7 +919,7 @@ static void lp_comm_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -1034,7 +1034,7 @@ static void rp_comm_rx_decode(struct ll_conn *conn, struct proc_ctx *ctx, struct #endif /* CONFIG_BT_CTLR_SCA_UPDATE */ default: /* Unknown opcode */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -1045,7 +1045,7 @@ static void rp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; @@ -1115,7 +1115,7 @@ static void rp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx) #endif /* CONFIG_BT_CTLR_SCA_UPDATE */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } ctx->tx_opcode = pdu->llctrl.opcode; @@ -1147,10 +1147,10 @@ static void rp_comm_ntf(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t gene /* Allocate ntf node */ ntf = ctx->node_ref.rx; ctx->node_ref.rx = NULL; - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); /* This should be an 'old' RX node, so put/sched when done */ - LL_ASSERT(ntf->hdr.type == NODE_RX_TYPE_RETAIN); + LL_ASSERT_DBG(ntf->hdr.type == NODE_RX_TYPE_RETAIN); /* And release memory if no NTF to be generated */ ntf->hdr.type = NODE_RX_TYPE_RELEASE; @@ -1159,7 +1159,7 @@ static void rp_comm_ntf(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t gene ntf->hdr.type = NODE_RX_TYPE_DC_PDU; ntf->hdr.handle = conn->lll.handle; pdu = (struct pdu_data *)ntf->pdu; - LL_ASSERT(ctx->proc == PROC_DATA_LENGTH_UPDATE); + LL_ASSERT_DBG(ctx->proc == PROC_DATA_LENGTH_UPDATE); llcp_ntf_encode_length_change(conn, pdu); } @@ -1291,7 +1291,7 @@ static void rp_comm_send_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t #endif /* CONFIG_BT_CTLR_SCA_UPDATE */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -1313,7 +1313,7 @@ static void rp_comm_st_postpone_terminate(struct ll_conn *conn, struct proc_ctx { switch (evt) { case RP_COMMON_EVT_RUN: - LL_ASSERT(ctx->proc == PROC_TERMINATE); + LL_ASSERT_DBG(ctx->proc == PROC_TERMINATE); /* Note: now we terminate, mimicking legacy LLCP behaviour * A check should be added to ensure that the ack of the terminate_ind was @@ -1415,7 +1415,7 @@ static void rp_comm_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c index 5fc5a261640f..d1a91c8d673d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c @@ -260,7 +260,7 @@ static void cu_ntf(struct ll_conn *conn, struct proc_ctx *ctx) /* Allocate ntf node */ ntf = ctx->node_ref.rx; ctx->node_ref.rx = NULL; - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); piggy_back = (ntf->hdr.type != NODE_RX_TYPE_RETAIN); @@ -300,7 +300,7 @@ static void lp_cu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode) if (!tx) { /* Allocate tx node if non pre-alloc'ed */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); } pdu = (struct pdu_data *)tx->pdu; @@ -323,7 +323,7 @@ static void lp_cu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode) #endif /* CONFIG_BT_CENTRAL */ default: /* Unknown opcode */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -408,7 +408,7 @@ static void lp_cu_send_conn_param_req(struct ll_conn *conn, struct proc_ctx *ctx #endif /* CONFIG_BT_PERIPHERAL */ default: /* Unknown role */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } @@ -491,7 +491,7 @@ static void lp_cu_st_idle(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t ev #endif /* CONFIG_BT_CENTRAL */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } break; @@ -761,7 +761,7 @@ static void lp_cu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_ break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } @@ -815,7 +815,7 @@ static void rp_cu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode) if (!tx) { /* Allocate tx node if non pre-alloc'ed */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); } pdu = (struct pdu_data *)tx->pdu; @@ -841,7 +841,7 @@ static void rp_cu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode) break; default: /* Unknown opcode */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -869,7 +869,7 @@ static void rp_cu_conn_param_req_ntf(struct ll_conn *conn, struct proc_ctx *ctx) /* Allocate ntf node */ ntf = ctx->node_ref.rx; ctx->node_ref.rx = NULL; - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); piggy_back = (ntf->hdr.type != NODE_RX_TYPE_RETAIN); @@ -903,7 +903,7 @@ static void rp_cu_send_conn_update_ind_finalize(struct ll_conn *conn, struct pro uint8_t evt, void *param) { /* Central role path, should not get here with !=NULL rx-node reference */ - LL_ASSERT(ctx->node_ref.rx == NULL); + LL_ASSERT_DBG(ctx->node_ref.rx == NULL); /* We pre-alloc NTF node */ ctx->node_ref.rx = llcp_ntf_alloc(); @@ -1015,7 +1015,7 @@ static void rp_cu_st_idle(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t ev break; default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } break; @@ -1162,7 +1162,7 @@ static void rp_cu_state_wait_conn_param_req_reply_continue(struct ll_conn *conn, } } else { /* Unknown role */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } break; default: @@ -1313,7 +1313,7 @@ static void rp_cu_st_wait_rx_conn_update_ind(struct ll_conn *conn, struct proc_c break; default: /* Unknown role */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } default: /* Ignore other evts */ @@ -1382,7 +1382,7 @@ static void rp_cu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_ break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c index 392f37963ae0..13fae31f9e50 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c @@ -187,7 +187,7 @@ static struct node_tx *llcp_lp_enc_tx(struct ll_conn *conn, struct proc_ctx *ctx /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; @@ -206,7 +206,7 @@ static struct node_tx *llcp_lp_enc_tx(struct ll_conn *conn, struct proc_ctx *ctx llcp_pdu_encode_pause_enc_rsp(pdu); break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); } ctx->tx_opcode = pdu->llctrl.opcode; @@ -228,7 +228,7 @@ static void lp_enc_ntf(struct ll_conn *conn, struct proc_ctx *ctx) /* Piggy-back on RX node */ ntf = ctx->node_ref.rx; ctx->node_ref.rx = NULL; - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); ntf->hdr.type = NODE_RX_TYPE_DC_PDU; ntf->hdr.handle = conn->lll.handle; @@ -244,7 +244,7 @@ static void lp_enc_ntf(struct ll_conn *conn, struct proc_ctx *ctx) ntf->hdr.type = NODE_RX_TYPE_ENC_REFRESH; } else { /* Should never happen */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } else { llcp_pdu_encode_reject_ind(pdu, ctx->data.enc.error); @@ -379,7 +379,7 @@ static inline uint8_t reject_error_code(struct pdu_data *pdu) #endif /* CONFIG_BT_CTLR_EXT_REJ_IND */ } else { /* Called with an invalid PDU */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); /* Keep compiler happy */ error = BT_HCI_ERR_UNSPECIFIED; @@ -639,7 +639,7 @@ static void lp_enc_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8 break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -705,7 +705,7 @@ static struct node_tx *llcp_rp_enc_tx(struct ll_conn *conn, struct proc_ctx *ctx /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; @@ -732,7 +732,7 @@ static struct node_tx *llcp_rp_enc_tx(struct ll_conn *conn, struct proc_ctx *ctx } break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); } ctx->tx_opcode = pdu->llctrl.opcode; @@ -755,7 +755,7 @@ static void rp_enc_ntf_ltk(struct ll_conn *conn, struct proc_ctx *ctx) /* Piggy-back on RX node */ ntf = ctx->node_ref.rx; ctx->node_ref.rx = NULL; - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); piggy_back = (ntf->hdr.type != NODE_RX_TYPE_RETAIN); @@ -780,7 +780,7 @@ static void rp_enc_ntf(struct ll_conn *conn, struct proc_ctx *ctx) /* Piggy-back on RX node */ ntf = ctx->node_ref.rx; ctx->node_ref.rx = NULL; - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); ntf->hdr.type = NODE_RX_TYPE_DC_PDU; ntf->hdr.handle = conn->lll.handle; @@ -795,7 +795,7 @@ static void rp_enc_ntf(struct ll_conn *conn, struct proc_ctx *ctx) ntf->hdr.type = NODE_RX_TYPE_ENC_REFRESH; } else { /* Should never happen */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -884,7 +884,7 @@ static void rp_enc_send_reject_ind(struct ll_conn *conn, struct proc_ctx *ctx, u */ } else { /* Shouldn't happen */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } } @@ -1232,7 +1232,7 @@ static void rp_enc_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8 break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c index 8c97bcdfb5f7..812d84955aa2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c @@ -79,13 +79,13 @@ void llcp_lr_check_done(struct ll_conn *conn, struct proc_ctx *ctx) struct proc_ctx *ctx_header; ctx_header = llcp_lr_peek(conn); - LL_ASSERT(ctx_header == ctx); + LL_ASSERT_DBG(ctx_header == ctx); /* If we have a node rx it must not be marked RETAIN as * the memory referenced would leak */ - LL_ASSERT(ctx->node_ref.rx == NULL || - ctx->node_ref.rx->hdr.type != NODE_RX_TYPE_RETAIN); + LL_ASSERT_DBG(ctx->node_ref.rx == NULL || + ctx->node_ref.rx->hdr.type != NODE_RX_TYPE_RETAIN); lr_dequeue(conn); @@ -326,7 +326,7 @@ void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, memq_link_t *link, #endif /* CONFIG_BT_CTLR_SCA_UPDATE */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -475,7 +475,7 @@ static void lr_act_run(struct ll_conn *conn) #endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -487,7 +487,7 @@ static void lr_act_complete(struct ll_conn *conn) struct proc_ctx *ctx; ctx = llcp_lr_peek(conn); - LL_ASSERT(ctx != NULL); + LL_ASSERT_DBG(ctx != NULL); /* Stop procedure response timeout timer */ llcp_lr_prt_stop(conn); @@ -617,7 +617,7 @@ static void lr_execute_fsm(struct ll_conn *conn, uint8_t evt, void *param) break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_past.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_past.c index 8b8f88147e0f..53e16b9f52ad 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_past.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_past.c @@ -326,7 +326,7 @@ static void rp_past_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint #endif /* CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY */ default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } @@ -400,7 +400,7 @@ static void lp_past_tx(struct ll_conn *conn, struct proc_ctx *ctx) /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; @@ -563,7 +563,7 @@ static void lp_past_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c index a9b48be2702f..9e8ebaf7a401 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c @@ -379,7 +379,7 @@ static void lp_pu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, vo struct node_tx *tx; struct pdu_data *pdu; - LL_ASSERT(ctx->node_ref.tx); + LL_ASSERT_DBG(ctx->node_ref.tx); #if defined(CONFIG_BT_CTLR_DATA_LENGTH) if (!((ctx->tx_opcode == PDU_DATA_LLCTRL_TYPE_PHY_REQ) && @@ -390,7 +390,7 @@ static void lp_pu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, vo return; } ctx->data.pu.ntf_dle_node = llcp_ntf_alloc(); - LL_ASSERT(ctx->data.pu.ntf_dle_node); + LL_ASSERT_DBG(ctx->data.pu.ntf_dle_node); } #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ @@ -417,7 +417,7 @@ static void lp_pu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, vo break; #endif /* CONFIG_BT_CENTRAL */ default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); } /* Enqueue LL Control PDU towards LLL */ @@ -435,10 +435,10 @@ static void pu_ntf(struct ll_conn *conn, struct proc_ctx *ctx) /* Piggy-back on stored RX node */ ntf = ctx->node_ref.rx; ctx->node_ref.rx = NULL; - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); if (ctx->data.pu.ntf_pu) { - LL_ASSERT(ntf->hdr.type == NODE_RX_TYPE_RETAIN); + LL_ASSERT_DBG(ntf->hdr.type == NODE_RX_TYPE_RETAIN); ntf->hdr.type = NODE_RX_TYPE_PHY_UPDATE; ntf->hdr.handle = conn->lll.handle; pdu = (struct node_rx_pu *)ntf->pdu; @@ -476,7 +476,7 @@ static void pu_dle_ntf(struct ll_conn *conn, struct proc_ctx *ctx) /* Signal to release pre-allocated node in case there is no DLE ntf */ ntf->hdr.type = NODE_RX_TYPE_RELEASE; } else { - LL_ASSERT(ntf); + LL_ASSERT_DBG(ntf); ntf->hdr.type = NODE_RX_TYPE_DC_PDU; ntf->hdr.handle = conn->lll.handle; @@ -646,7 +646,7 @@ static void lp_pu_st_wait_tx_ack_phy_req(struct ll_conn *conn, struct proc_ctx * #endif /* CONFIG_BT_PERIPHERAL */ default: /* Unknown role */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } break; @@ -675,7 +675,7 @@ static void lp_pu_st_wait_tx_ack_phy_update_ind(struct ll_conn *conn, struct pro { switch (evt) { case LP_PU_EVT_ACK: - LL_ASSERT(conn->lll.role == BT_HCI_ROLE_CENTRAL); + LL_ASSERT_DBG(conn->lll.role == BT_HCI_ROLE_CENTRAL); if (ctx->data.pu.p_to_c_phy || ctx->data.pu.c_to_p_phy) { /* Either phys should change */ if (ctx->data.pu.c_to_p_phy) { @@ -711,7 +711,7 @@ static void lp_pu_st_wait_rx_phy_update_ind(struct ll_conn *conn, struct proc_ct { switch (evt) { case LP_PU_EVT_PHY_UPDATE_IND: - LL_ASSERT(conn->lll.role == BT_HCI_ROLE_PERIPHERAL); + LL_ASSERT_DBG(conn->lll.role == BT_HCI_ROLE_PERIPHERAL); llcp_rr_set_incompat(conn, INCOMPAT_RESERVED); llcp_pdu_decode_phy_update_ind(ctx, (struct pdu_data *)param); const uint8_t end_procedure = pu_check_update_ind(conn, ctx); @@ -867,7 +867,7 @@ static void lp_pu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_ #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } @@ -930,7 +930,7 @@ static void rp_pu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, vo struct node_tx *tx; struct pdu_data *pdu; - LL_ASSERT(ctx->node_ref.tx); + LL_ASSERT_DBG(ctx->node_ref.tx); #if defined(CONFIG_BT_CTLR_DATA_LENGTH) if (!llcp_ntf_alloc_is_available()) { @@ -940,7 +940,7 @@ static void rp_pu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, vo } ctx->data.pu.ntf_dle_node = llcp_ntf_alloc(); - LL_ASSERT(ctx->data.pu.ntf_dle_node); + LL_ASSERT_DBG(ctx->data.pu.ntf_dle_node); #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ tx = ctx->node_ref.tx; @@ -967,7 +967,7 @@ static void rp_pu_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, vo break; #endif /* CONFIG_BT_CENTRAL */ default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); } /* Enqueue LL Control PDU towards LLL */ @@ -1073,7 +1073,7 @@ static void rp_pu_st_wait_rx_phy_req(struct ll_conn *conn, struct proc_ctx *ctx, #endif /* CONFIG_BT_PERIPHERAL */ default: /* Unknown role */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } break; default: @@ -1105,7 +1105,7 @@ static void rp_pu_st_wait_tx_ack_phy(struct ll_conn *conn, struct proc_ctx *ctx, if (0) { #if defined(CONFIG_BT_PERIPHERAL) } else if (ctx->state == RP_PU_STATE_WAIT_TX_ACK_PHY_RSP) { - LL_ASSERT(conn->lll.role == BT_HCI_ROLE_PERIPHERAL); + LL_ASSERT_DBG(conn->lll.role == BT_HCI_ROLE_PERIPHERAL); /* When we act as peripheral apply timing restriction */ pu_set_timing_restrict( conn, pu_select_phy_timing_restrict(conn, ctx->data.pu.tx)); @@ -1114,7 +1114,7 @@ static void rp_pu_st_wait_tx_ack_phy(struct ll_conn *conn, struct proc_ctx *ctx, #endif /* CONFIG_BT_PERIPHERAL */ #if defined(CONFIG_BT_CENTRAL) } else if (ctx->state == RP_PU_STATE_WAIT_TX_ACK_PHY_UPDATE_IND) { - LL_ASSERT(conn->lll.role == BT_HCI_ROLE_CENTRAL); + LL_ASSERT_DBG(conn->lll.role == BT_HCI_ROLE_CENTRAL); if (ctx->data.pu.c_to_p_phy || ctx->data.pu.p_to_c_phy) { /* UPDATE_IND acked, so lets await instant */ if (ctx->data.pu.c_to_p_phy) { @@ -1289,7 +1289,7 @@ static void rp_pu_execute_fsm(struct ll_conn *conn, struct proc_ctx *ctx, uint8_ #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index 185cad7911d1..3a90a9d950ba 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -104,7 +104,7 @@ static bool proc_with_instant(struct proc_ctx *ctx) return 1U; default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -117,12 +117,12 @@ void llcp_rr_check_done(struct ll_conn *conn, struct proc_ctx *ctx) struct proc_ctx *ctx_header; ctx_header = llcp_rr_peek(conn); - LL_ASSERT(ctx_header == ctx); + LL_ASSERT_DBG(ctx_header == ctx); /* If we have a node rx it must not be marked RETAIN as * the memory referenced would leak */ - LL_ASSERT(ctx->node_ref.rx == NULL || + LL_ASSERT_DBG(ctx->node_ref.rx == NULL || ctx->node_ref.rx->hdr.type != NODE_RX_TYPE_RETAIN); rr_dequeue(conn); @@ -319,7 +319,7 @@ void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, memq_link_t *link, #endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -459,7 +459,7 @@ static void rr_act_run(struct ll_conn *conn) #endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */ default: /* Unknown procedure */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); break; } @@ -475,7 +475,7 @@ static void rr_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode) /* Allocate tx node */ tx = llcp_tx_alloc(conn, ctx); - LL_ASSERT(tx); + LL_ASSERT_DBG(tx); pdu = (struct pdu_data *)tx->pdu; @@ -502,7 +502,7 @@ static void rr_tx(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t opcode) llcp_pdu_encode_unknown_rsp(ctx, pdu); break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); } ctx->tx_opcode = pdu->llctrl.opcode; @@ -515,7 +515,7 @@ static void rr_act_reject(struct ll_conn *conn) { struct proc_ctx *ctx = llcp_rr_peek(conn); - LL_ASSERT(ctx != NULL); + LL_ASSERT_DBG(ctx != NULL); if (llcp_rr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { rr_set_state(conn, RR_STATE_REJECT); @@ -531,7 +531,7 @@ static void rr_act_unsupported(struct ll_conn *conn) { struct proc_ctx *ctx = llcp_rr_peek(conn); - LL_ASSERT(ctx != NULL); + LL_ASSERT_DBG(ctx != NULL); if (llcp_rr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { rr_set_state(conn, RR_STATE_UNSUPPORTED); @@ -550,7 +550,7 @@ static void rr_act_complete(struct ll_conn *conn) rr_set_collision(conn, 0U); ctx = llcp_rr_peek(conn); - LL_ASSERT(ctx != NULL); + LL_ASSERT_DBG(ctx != NULL); /* Stop procedure response timeout timer */ llcp_rr_prt_stop(conn); @@ -777,7 +777,7 @@ static void rr_execute_fsm(struct ll_conn *conn, uint8_t evt, void *param) break; default: /* Unknown state */ - LL_ASSERT(0); + LL_ASSERT_DBG(0); } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c index 8032b18e9950..aa6db211ed19 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c @@ -250,7 +250,7 @@ void ull_periph_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr, * complete event. */ node = pdu_adv; - LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cc)); + LL_ASSERT_DBG(IS_PTR_ALIGNED(node, struct node_rx_cc)); /* Populate the fields required for connection complete event */ cc = node; @@ -334,7 +334,7 @@ void ull_periph_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr, link = rx->hdr.link; handle = ull_adv_handle_get(adv); - LL_ASSERT(handle < BT_CTLR_ADV_SET); + LL_ASSERT_DBG(handle < BT_CTLR_ADV_SET); rx->hdr.type = NODE_RX_TYPE_EXT_ADV_TERMINATE; rx->hdr.handle = handle; @@ -494,8 +494,8 @@ void ull_periph_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr, ticks_slot_overhead), ull_periph_ticker_cb, conn, ticker_op_cb, (void *)__LINE__); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); #if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) /* enable ticker job, irrespective of disabled in this function so @@ -520,8 +520,8 @@ void ull_periph_latency_cancel(struct ll_conn *conn, uint16_t handle) 0, 0, 0, 0, 1, 0, ticker_update_latency_cancel_op_cb, (void *)conn); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); } } @@ -578,7 +578,7 @@ void ull_periph_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&conn->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); /* Increment event counter */ conn->event_counter += (lazy + 1U); @@ -594,7 +594,7 @@ void ull_periph_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ err = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!err); + LL_ASSERT_ERR(!err); /* De-mux remaining tx nodes from FIFO */ ull_conn_tx_demux(UINT8_MAX); @@ -664,15 +664,15 @@ static void invalid_release(struct ull_hdr *hdr, struct lll_conn *lll, static void ticker_op_stop_adv_cb(uint32_t status, void *param) { - LL_ASSERT(status != TICKER_STATUS_FAILURE || - param == ull_disable_mark_get()); + LL_ASSERT_ERR((status != TICKER_STATUS_FAILURE) || + (param == ull_disable_mark_get())); } static void ticker_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); } static void ticker_update_latency_cancel_op_cb(uint32_t ticker_status, @@ -680,7 +680,7 @@ static void ticker_update_latency_cancel_op_cb(uint32_t ticker_status, { struct ll_conn *conn = param; - LL_ASSERT(ticker_status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(ticker_status == TICKER_STATUS_SUCCESS); conn->periph.latency_cancel = 0U; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index dd360c9f9eb8..21ff94e90bb6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -158,7 +158,7 @@ void ull_peripheral_iso_release(uint16_t cis_handle) struct ll_conn_iso_group *cig; cis = ll_conn_iso_stream_get(cis_handle); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); cig = cis->group; @@ -318,7 +318,7 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, } conn = ll_conn_get(cis->lll.acl_handle); - LL_ASSERT(conn != NULL); + LL_ASSERT_DBG(conn != NULL); cis_offset = sys_get_le24(ind->cis_offset); @@ -366,7 +366,7 @@ static void ticker_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); } void ull_peripheral_iso_update_ticker(struct ll_conn_iso_group *cig, @@ -378,8 +378,8 @@ void ull_peripheral_iso_update_ticker(struct ll_conn_iso_group *cig, uint8_t ticker_id_cig = TICKER_ID_CONN_ISO_BASE + ll_conn_iso_group_handle_get(cig); uint32_t ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, ticker_id_cig, ticker_op_cb, NULL); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); ticker_status = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, @@ -393,8 +393,8 @@ void ull_peripheral_iso_update_ticker(struct ll_conn_iso_group *cig, ull_conn_iso_ticker_cb, cig, ticker_op_cb, NULL); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); } @@ -412,8 +412,9 @@ void ull_peripheral_iso_update_peer_sca(struct ll_conn *acl) if (!cig || !cig->lll.num_cis) { continue; } + cis = ll_conn_iso_stream_get_by_group(cig, NULL); - LL_ASSERT(cis); + LL_ASSERT_DBG(cis); uint16_t cis_handle = cis->lll.handle; diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan.c b/subsys/bluetooth/controller/ll_sw/ull_scan.c index 493c2330db0b..514072643e16 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan.c @@ -696,7 +696,7 @@ uint8_t ull_scan_disable(uint8_t handle, struct ll_scan_set *scan) * sync role. */ parent = aux->parent; - LL_ASSERT(!parent || (parent != aux_scan_lll)); + LL_ASSERT_DBG(!parent || (parent != aux_scan_lll)); } } #endif /* !CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS */ @@ -727,7 +727,7 @@ void ull_scan_done(struct node_rx_event_done *done) lll->duration_reload = 0U; handle = ull_scan_handle_get(scan); - LL_ASSERT(handle < BT_CTLR_SCAN_SET); + LL_ASSERT_DBG(handle < BT_CTLR_SCAN_SET); #if defined(CONFIG_BT_CTLR_PHY_CODED) /* Prevent duplicate terminate event if ull_scan_done get called by @@ -751,8 +751,8 @@ void ull_scan_done(struct node_rx_event_done *done) (TICKER_ID_SCAN_BASE + handle), ticker_stop_ext_op_cb, scan); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } void ull_scan_term_dequeue(uint8_t handle) @@ -760,7 +760,7 @@ void ull_scan_term_dequeue(uint8_t handle) struct ll_scan_set *scan; scan = ull_scan_set_get(handle); - LL_ASSERT(scan); + LL_ASSERT_DBG(scan); scan->is_enabled = 0U; @@ -773,7 +773,7 @@ void ull_scan_term_dequeue(uint8_t handle) uint8_t err; err = disable(SCAN_HANDLE_PHY_CODED); - LL_ASSERT(!err); + LL_ASSERT_ERR(!err); } } else { struct ll_scan_set *scan_1m; @@ -783,7 +783,7 @@ void ull_scan_term_dequeue(uint8_t handle) uint8_t err; err = disable(SCAN_HANDLE_1M); - LL_ASSERT(!err); + LL_ASSERT_ERR(!err); } } #endif /* CONFIG_BT_CTLR_PHY_CODED */ @@ -924,7 +924,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&scan->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); /* Append timing parameters */ p.ticks_at_expire = ticks_at_expire; @@ -937,7 +937,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); #if defined(CONFIG_BT_CTLR_ADV_EXT) if (lll->duration_expire) { @@ -955,7 +955,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, scan->duration_lazy - elapsed; handle = ull_scan_handle_get(scan); - LL_ASSERT(handle < BT_CTLR_SCAN_SET); + LL_ASSERT_DBG(handle < BT_CTLR_SCAN_SET); ret = ticker_update(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, @@ -963,8 +963,8 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, handle), 0, 0, 0, 0, duration_lazy, 0, NULL, NULL); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } lll->duration_expire = 0U; @@ -973,15 +973,15 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, uint8_t handle; handle = ull_scan_handle_get(scan); - LL_ASSERT(handle < BT_CTLR_SCAN_SET); + LL_ASSERT_DBG(handle < BT_CTLR_SCAN_SET); lll->duration_expire = lll->duration_reload; ret = ticker_update(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, (TICKER_ID_SCAN_BASE + handle), 0, 0, 0, 0, 1, 1, NULL, NULL); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } #endif /* CONFIG_BT_CTLR_ADV_EXT */ @@ -1105,7 +1105,7 @@ static void ticker_stop_ext_op_cb(uint32_t status, void *param) mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void ext_disable(void *param) @@ -1126,14 +1126,14 @@ static void ext_disable(void *param) /* Setup disabled callback to be called when ref count * returns to zero. */ - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = mfy.param; hdr->disabled_cb = ext_disabled_cb; /* Trigger LLL disable */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } else { /* No pending LLL events */ ext_disabled_cb(&scan->lll); diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 953575885bc5..012168b768d9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -215,7 +215,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) rx_incomplete = NULL; lll = ftr->param; - LL_ASSERT(!lll->lll_aux); + LL_ASSERT_DBG(!lll->lll_aux); scan = HDR_LLL2ULL(lll); sync = sync_create_get(scan); @@ -234,7 +234,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) rx_incomplete = NULL; lll = ftr->param; - LL_ASSERT(!lll->lll_aux); + LL_ASSERT_DBG(!lll->lll_aux); scan = HDR_LLL2ULL(lll); sync = sync_create_get(scan); @@ -259,7 +259,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) /* aux parent will be NULL for periodic sync */ lll = aux->parent; - LL_ASSERT(lll); + LL_ASSERT_DBG(lll); ticker_yield_handle = TICKER_ID_SCAN_AUX_BASE + aux_handle_get(aux); @@ -280,10 +280,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) * is being received before we process the node here. */ lll_aux = ftr->lll_aux; - LL_ASSERT(lll_aux); + LL_ASSERT_DBG(lll_aux); aux = HDR_LLL2ULL(lll_aux); - LL_ASSERT(lll == aux->parent); + LL_ASSERT_DBG(lll == aux->parent); ticker_yield_handle = TICKER_NULL; @@ -301,10 +301,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) * is being received before we process the node here. */ lll_aux = ftr->lll_aux; - LL_ASSERT(lll_aux); + LL_ASSERT_DBG(lll_aux); aux = HDR_LLL2ULL(lll_aux); - LL_ASSERT(sync_lll == aux->parent); + LL_ASSERT_DBG(sync_lll == aux->parent); ticker_yield_handle = TICKER_NULL; } @@ -340,7 +340,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) break; #endif /* CONFIG_BT_CTLR_PHY_CODED */ default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); + return; } @@ -375,7 +376,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) * passed in the node rx footer field. */ sync_lll = ftr->param; - LL_ASSERT(!sync_lll->lll_aux); + LL_ASSERT_DBG(!sync_lll->lll_aux); ull_sync = HDR_LLL2ULL(sync_lll); rx->hdr.handle = ull_sync_handle_get(ull_sync); @@ -406,7 +407,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) } break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); + return; } @@ -601,7 +603,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) } if (is_scan_req) { - LL_ASSERT(aux && aux->rx_last); + LL_ASSERT_DBG(aux && aux->rx_last); aux->rx_last->rx_ftr.extra = rx; aux->rx_last = rx; @@ -818,7 +820,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) * scheduling, or receiving a chain then it will * reuse the aux context. */ - LL_ASSERT(!lll->lll_aux || (lll->lll_aux == lll_aux)); + LL_ASSERT_DBG(!lll->lll_aux || (lll->lll_aux == lll_aux)); /* Associate Scan context with the Aux context so that * it can continue reception in LLL scheduling. @@ -841,7 +843,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) /* Switching to ULL scheduling to receive auxiliary PDUs */ if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) { - LL_ASSERT(scan); + LL_ASSERT_DBG(scan); /* Do not ULL schedule if scan disable requested */ if (unlikely(scan->is_stop)) { @@ -857,8 +859,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) } else { struct ll_sync_set *sync_set; - LL_ASSERT(sync_lll && - (!sync_lll->lll_aux || sync_lll->lll_aux == lll_aux)); + LL_ASSERT_ERR(sync_lll && + (!sync_lll->lll_aux || sync_lll->lll_aux == lll_aux)); /* Do not ULL schedule if sync terminate requested */ sync_set = HDR_LLL2ULL(sync_lll); @@ -917,8 +919,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) ticks_aux_offset - ticks_slot_offset), NULL, NULL); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); } aux_handle = aux_handle_get(aux); @@ -933,10 +935,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) (aux->ull.ticks_slot + ticks_slot_overhead), ticker_cb, aux, ticker_op_cb, aux); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY) || - ((ticker_status == TICKER_STATUS_FAILURE) && - IS_ENABLED(CONFIG_BT_TICKER_LOW_LAT))); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY) || + ((ticker_status == TICKER_STATUS_FAILURE) && + IS_ENABLED(CONFIG_BT_TICKER_LOW_LAT))); #if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) /* enable ticker job, queued ticker operation will be handled @@ -960,7 +962,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) * immediately since we are in sync context. */ if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || aux->rx_last) { - LL_ASSERT(scan); + LL_ASSERT_DBG(scan); /* If scan is being disabled, rx could already be * enqueued before coming here to ull_scan_aux_rx_flush. @@ -990,7 +992,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) } else { const struct ll_sync_set *sync_set; - LL_ASSERT(sync_lll); + LL_ASSERT_DBG(sync_lll); ll_rx_put_sched(link, rx); @@ -1000,7 +1002,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) } } - LL_ASSERT(aux->parent); + LL_ASSERT_DBG(aux->parent); flush_safe(aux); @@ -1028,7 +1030,7 @@ void ull_scan_aux_done(struct node_rx_event_done *done) struct ll_sync_set *sync; sync = CONTAINER_OF(done->param, struct ll_sync_set, ull); - LL_ASSERT(ull_sync_is_valid_get(sync)); + LL_ASSERT_DBG(ull_sync_is_valid_get(sync)); /* Auxiliary context will be flushed by ull_scan_aux_stop() */ if (unlikely(sync->is_stop) || !sync->lll.lll_aux) { @@ -1036,16 +1038,16 @@ void ull_scan_aux_done(struct node_rx_event_done *done) } aux = HDR_LLL2ULL(sync->lll.lll_aux); - LL_ASSERT(aux->parent); + LL_ASSERT_DBG(aux->parent); } else { struct ll_scan_set *scan; struct lll_scan *lll; lll = aux->parent; - LL_ASSERT(lll); + LL_ASSERT_DBG(lll); scan = HDR_LLL2ULL(lll); - LL_ASSERT(ull_scan_is_valid_get(scan)); + LL_ASSERT_DBG(ull_scan_is_valid_get(scan)); /* Auxiliary context will be flushed by ull_scan_aux_stop() */ if (unlikely(scan->is_stop)) { @@ -1086,7 +1088,7 @@ void *ull_scan_aux_lll_parent_get(struct lll_scan_aux *lll, struct lll_scan *lllscan; lllscan = aux->parent; - LL_ASSERT(lllscan); + LL_ASSERT_DBG(lllscan); scan = HDR_LLL2ULL(lllscan); *is_lll_scan = !!ull_scan_is_valid_get(scan); @@ -1196,7 +1198,8 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_pdu *rx) rx->rx_ftr.extra = NULL; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); + lll_aux = NULL; } @@ -1208,7 +1211,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_pdu *rx) aux = HDR_LLL2ULL(lll_aux); lll = aux->parent; - LL_ASSERT(lll); + LL_ASSERT_DBG(lll); scan = HDR_LLL2ULL(lll); scan = ull_scan_is_valid_get(scan); @@ -1222,12 +1225,13 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_pdu *rx) sync = HDR_LLL2ULL(sync_lll); is_stop = sync->is_stop; } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); + return; } if (!is_stop) { - LL_ASSERT(aux->parent); + LL_ASSERT_DBG(aux->parent); flush_safe(aux); @@ -1287,7 +1291,7 @@ int ull_scan_aux_stop(struct ll_scan_aux_set *aux) struct lll_scan *lll; lll = aux->parent; - LL_ASSERT(lll); + LL_ASSERT_DBG(lll); scan = HDR_LLL2ULL(lll); scan = ull_scan_is_valid_get(scan); @@ -1308,7 +1312,7 @@ int ull_scan_aux_stop(struct ll_scan_aux_set *aux) mfy.param = aux; ret = mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); return 0; } @@ -1333,7 +1337,7 @@ static inline void aux_release(struct ll_scan_aux_set *aux) /* Clear the parent so that when scan is being disabled then this * auxiliary context shall not associate itself from being disable. */ - LL_ASSERT(aux->parent); + LL_ASSERT_DBG(aux->parent); aux->parent = NULL; mem_release(aux, &scan_aux_free); @@ -1350,7 +1354,7 @@ static void done_disabled_cb(void *param) struct ll_scan_aux_set *aux; aux = param; - LL_ASSERT(aux->parent); + LL_ASSERT_DBG(aux->parent); flush(aux); } @@ -1362,7 +1366,7 @@ static void flush_safe(void *param) uint8_t ref; aux = param; - LL_ASSERT(aux->parent); + LL_ASSERT_DBG(aux->parent); /* ref == 0 * All PDUs were scheduled from LLL and there is no pending done @@ -1382,9 +1386,9 @@ static void flush_safe(void *param) * cannot overlap, i.e. ULL reference count * shall be less than 2. */ - LL_ASSERT(ref < 2U); + LL_ASSERT_DBG(ref < 2U); - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = aux; hdr->disabled_cb = done_disabled_cb; @@ -1406,7 +1410,7 @@ static void flush(void *param) * auxiliary channel PDUs. */ aux = param; - LL_ASSERT(aux->parent); + LL_ASSERT_DBG(aux->parent); rx = aux->rx_head; if (rx) { @@ -1456,7 +1460,7 @@ static void aux_sync_partial(void *param) rx = aux->rx_head; aux->rx_head = NULL; - LL_ASSERT(rx); + LL_ASSERT_DBG(rx); rx->rx_ftr.aux_sched = 1U; ll_rx_put_sched(rx->hdr.link, rx); @@ -1468,7 +1472,7 @@ static void aux_sync_incomplete(void *param) struct ll_scan_aux_set *aux; aux = param; - LL_ASSERT(aux->parent); + LL_ASSERT_DBG(aux->parent); /* ULL scheduling succeeded hence no backup node rx present, use the * extra node rx reserved for incomplete data status generation. @@ -1480,7 +1484,7 @@ static void aux_sync_incomplete(void *param) /* get reference to sync context */ lll = aux->parent; - LL_ASSERT(lll); + LL_ASSERT_DBG(lll); sync = HDR_LLL2ULL(lll); /* reset data len total */ @@ -1488,7 +1492,7 @@ static void aux_sync_incomplete(void *param) /* pick extra node rx stored in aux context */ rx = aux->rx_incomplete; - LL_ASSERT(rx); + LL_ASSERT_DBG(rx); aux->rx_incomplete = NULL; /* prepare sync report with failure */ @@ -1508,7 +1512,7 @@ static void aux_sync_incomplete(void *param) aux->rx_head = rx; } - LL_ASSERT(!ull_ref_get(&aux->ull)); + LL_ASSERT_DBG(!ull_ref_get(&aux->ull)); flush(aux); #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */ @@ -1529,7 +1533,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&aux->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); /* Append timing parameters */ p.ticks_at_expire = ticks_at_expire; @@ -1542,7 +1546,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_PREPARE_O(1); } @@ -1560,7 +1564,7 @@ static void ticker_op_cb(uint32_t status, void *param) aux = param; sync_lll = aux->parent; - LL_ASSERT(sync_lll); + LL_ASSERT_DBG(sync_lll); sync = HDR_LLL2ULL(sync_lll); sync = ull_sync_is_valid_get(sync); @@ -1581,7 +1585,7 @@ static void ticker_op_cb(uint32_t status, void *param) struct ll_scan_aux_set *aux; aux = param; - LL_ASSERT(aux->parent); + LL_ASSERT_DBG(aux->parent); mfy.fp = flush_safe; } @@ -1591,7 +1595,7 @@ static void ticker_op_cb(uint32_t status, void *param) ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } #else /* CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS */ @@ -1648,7 +1652,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) rx_incomplete = NULL; lll = ftr->param; - LL_ASSERT(!lll->lll_aux); + LL_ASSERT_DBG(!lll->lll_aux); scan = HDR_LLL2ULL(lll); sync = sync_create_get(scan); @@ -1664,7 +1668,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) rx_incomplete = NULL; lll = ftr->param; - LL_ASSERT(!lll->lll_aux); + LL_ASSERT_DBG(!lll->lll_aux); scan = HDR_LLL2ULL(lll); sync = sync_create_get(scan); @@ -1686,7 +1690,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) /* chain parent will be NULL for periodic sync */ lll = chain->parent; - LL_ASSERT(lll); + LL_ASSERT_DBG(lll); } else if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || ull_scan_is_valid_get(HDR_LLL2ULL(ftr->param))) { @@ -1700,10 +1704,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) lll = ftr->param; lll_aux = lll->lll_aux; - LL_ASSERT(lll_aux); + LL_ASSERT_DBG(lll_aux); chain = CONTAINER_OF(lll_aux, struct ll_scan_aux_chain, lll); - LL_ASSERT(lll == chain->parent); + LL_ASSERT_DBG(lll == chain->parent); } else { lll = NULL; @@ -1713,10 +1717,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) sync_lll = ftr->param; lll_aux = sync_lll->lll_aux; - LL_ASSERT(lll_aux); + LL_ASSERT_DBG(lll_aux); chain = CONTAINER_OF(lll_aux, struct ll_scan_aux_chain, lll); - LL_ASSERT(sync_lll == chain->parent); + LL_ASSERT_DBG(sync_lll == chain->parent); } if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) { @@ -1750,7 +1754,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) break; #endif /* CONFIG_BT_CTLR_PHY_CODED */ default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); + return; } @@ -1785,7 +1790,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) * passed in the node rx footer field. */ sync_lll = ftr->param; - LL_ASSERT(!sync_lll->lll_aux); + LL_ASSERT_DBG(!sync_lll->lll_aux); ull_sync = HDR_LLL2ULL(sync_lll); rx->hdr.handle = ull_sync_handle_get(ull_sync); @@ -1813,7 +1818,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) } break; default: - LL_ASSERT(0); + LL_ASSERT_DBG(0); + return; } @@ -2009,7 +2015,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) PDU_ADV_AUX_PTR_PHY_GET(aux_ptr) == EXT_ADV_AUX_PHY_LE_CODED) || (aux_ptr->chan_idx >= CHM_USED_COUNT_MAX)) { if (is_scan_req) { - LL_ASSERT(chain && chain->rx_last); + LL_ASSERT_DBG(chain && chain->rx_last); chain->rx_last->rx_ftr.extra = rx; chain->rx_last = rx; @@ -2207,7 +2213,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) /* Switching to ULL scheduling to receive auxiliary PDUs */ if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || lll) { - LL_ASSERT(scan); + LL_ASSERT_DBG(scan); /* Do not ULL schedule if scan disable requested */ if (unlikely(scan->is_stop)) { @@ -2223,8 +2229,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) } else { struct ll_sync_set *sync_set; - LL_ASSERT(sync_lll && - (!sync_lll->lll_aux || sync_lll->lll_aux == lll_aux)); + LL_ASSERT_ERR(sync_lll && + (!sync_lll->lll_aux || sync_lll->lll_aux == lll_aux)); /* Do not ULL schedule if sync terminate requested */ sync_set = HDR_LLL2ULL(sync_lll); @@ -2278,7 +2284,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) * immediately since we are in sync context. */ if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC) || chain->rx_last) { - LL_ASSERT(scan); + LL_ASSERT_DBG(scan); /* rx could already be enqueued before coming here - * check if rx not the last in the list of received PDUs @@ -2291,12 +2297,12 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_pdu *rx) chain->rx_last = rx; } } else { - LL_ASSERT(sync_lll); + LL_ASSERT_DBG(sync_lll); ll_rx_put_sched(link, rx); } - LL_ASSERT(chain->parent); + LL_ASSERT_DBG(chain->parent); flush_safe(chain); @@ -2318,7 +2324,7 @@ void ull_scan_aux_done(struct node_rx_event_done *done) /* Get reference to chain */ chain = CONTAINER_OF(done->extra.lll, struct ll_scan_aux_chain, lll); - LL_ASSERT(scan_aux_chain_is_valid_get(chain)); + LL_ASSERT_DBG(scan_aux_chain_is_valid_get(chain)); /* Remove chain from active list */ chain_remove_from_list(&scan_aux_set.active_chains, chain); @@ -2343,7 +2349,7 @@ void *ull_scan_aux_lll_parent_get(struct lll_scan_aux *lll, struct lll_scan *lllscan; lllscan = chain->parent; - LL_ASSERT(lllscan); + LL_ASSERT_DBG(lllscan); scan = HDR_LLL2ULL(lllscan); *is_lll_scan = !!ull_scan_is_valid_get(scan); @@ -2419,7 +2425,8 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_pdu *rx) rx->rx_ftr.extra = NULL; } } else { - LL_ASSERT(0); + LL_ASSERT_DBG(0); + lll_aux = NULL; } @@ -2431,7 +2438,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_pdu *rx) chain = CONTAINER_OF(lll_aux, struct ll_scan_aux_chain, lll); lll = chain->parent; - LL_ASSERT(lll); + LL_ASSERT_DBG(lll); scan = HDR_LLL2ULL(lll); scan = ull_scan_is_valid_get(scan); @@ -2447,7 +2454,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_pdu *rx) } if (!is_stop) { - LL_ASSERT(chain->parent); + LL_ASSERT_DBG(chain->parent); /* Remove chain from active list and flush */ chain_remove_from_list(&scan_aux_set.active_chains, chain); @@ -2474,8 +2481,8 @@ static void scan_aux_stop_all_chains_for_parent(void *parent) /* Scheduled head is about to be removed - stop running ticker */ ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, TICKER_ID_SCAN_AUX, NULL, NULL); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); ticker_stopped = true; } @@ -2531,7 +2538,7 @@ static void scan_aux_stop_all_chains_for_parent(void *parent) mfy.param = &curr->lll; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } } else { prev = curr; @@ -2555,7 +2562,7 @@ int ull_scan_aux_stop(void *parent) /* Stop chains in ULL execution context */ mfy.param = parent; ret = mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); /* Wait for chains to be stopped before returning */ (void)k_sem_take(&sem_scan_aux_stop, K_FOREVER); @@ -2587,7 +2594,7 @@ static inline void aux_chain_release(struct ll_scan_aux_chain *chain) /* Clear the parent so that when scan is being disabled then this * auxiliary context shall not associate itself from being disable. */ - LL_ASSERT(chain->parent); + LL_ASSERT_DBG(chain->parent); chain->parent = NULL; mem_release(chain, &scan_aux_free); @@ -2614,7 +2621,7 @@ static void flush_safe(void *param) struct ll_scan_aux_chain *chain; chain = param; - LL_ASSERT(chain->parent); + LL_ASSERT_DBG(chain->parent); if (chain_is_in_list(scan_aux_set.flushing_chains, chain)) { /* Chain already marked for flushing */ @@ -2646,7 +2653,7 @@ static void flush(struct ll_scan_aux_chain *chain) /* Debug check that parent was assigned when allocated for reception of * auxiliary channel PDUs. */ - LL_ASSERT(chain->parent); + LL_ASSERT_DBG(chain->parent); /* Chain is being flushed now - remove from flushing_chains if present */ chain_remove_from_list(&scan_aux_set.flushing_chains, chain); @@ -2702,7 +2709,7 @@ static void flush(struct ll_scan_aux_chain *chain) sync_lll = chain->parent; sync = HDR_LLL2ULL(sync_lll); - LL_ASSERT(sync->is_stop || sync_lll->lll_aux); + LL_ASSERT_DBG(sync->is_stop || sync_lll->lll_aux); sync_lll->lll_aux = NULL; } @@ -2716,16 +2723,16 @@ static void aux_sync_incomplete(struct ll_scan_aux_chain *chain) struct node_rx_pdu *rx; struct lll_sync *lll; - LL_ASSERT(chain->parent); + LL_ASSERT_DBG(chain->parent); /* get reference to sync context */ lll = chain->parent; - LL_ASSERT(lll); + LL_ASSERT_DBG(lll); sync = HDR_LLL2ULL(lll); /* pick extra node rx stored in sync context */ rx = sync->rx_incomplete; - LL_ASSERT(rx); + LL_ASSERT_DBG(rx); sync->rx_incomplete = NULL; /* prepare sync report with failure */ @@ -2810,16 +2817,16 @@ static void chain_start_ticker(struct ll_scan_aux_chain *chain, bool replace) (chain->ticker_ticks - ticks_slot_offset), NULL, NULL); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); } #endif /* !CONFIG_BT_TICKER_SLOT_AGNOSTIC */ if (replace) { ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, TICKER_ID_SCAN_AUX, NULL, NULL); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); } ticker_status = ticker_start(TICKER_INSTANCE_ID_CTLR, @@ -2834,13 +2841,13 @@ static void chain_start_ticker(struct ll_scan_aux_chain *chain, bool replace) ticks_slot_overhead), ticker_cb, chain, ticker_op_cb, chain); #if defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC) - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY)); #else - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY) || - ((ticker_status == TICKER_STATUS_FAILURE) && - IS_ENABLED(CONFIG_BT_TICKER_LOW_LAT))); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY) || + ((ticker_status == TICKER_STATUS_FAILURE) && + IS_ENABLED(CONFIG_BT_TICKER_LOW_LAT))); #endif /* !CONFIG_BT_TICKER_SLOT_AGNOSTIC */ #if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) @@ -2866,10 +2873,10 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&scan_aux_set.ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); /* The chain should always be the first in the sched_chains list */ - LL_ASSERT(scan_aux_set.sched_chains == chain); + LL_ASSERT_DBG(scan_aux_set.sched_chains == chain); /* Move chain to active list */ chain_remove_from_list(&scan_aux_set.sched_chains, chain); @@ -2886,7 +2893,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); if (scan_aux_set.sched_chains) { /* Start ticker for next chain */ @@ -2916,7 +2923,7 @@ static void ticker_start_failed(void *param) static void ticker_op_cb(uint32_t status, void *param) { #if defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC) - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); #else /* !CONFIG_BT_TICKER_SLOT_AGNOSTIC */ static memq_link_t link; static struct mayfly mfy = {0, 0, &link, NULL, ticker_start_failed}; @@ -2930,7 +2937,7 @@ static void ticker_op_cb(uint32_t status, void *param) ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 1, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); #endif /* !CONFIG_BT_TICKER_SLOT_AGNOSTIC */ } diff --git a/subsys/bluetooth/controller/ll_sw/ull_sched.c b/subsys/bluetooth/controller/ll_sw/ull_sched.c index 116ea101d133..5309e5c1f2a5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sched.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sched.c @@ -465,12 +465,12 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, /* Using a local variable to address the Coverity rule: * Incorrect expression (ASSERT_SIDE_EFFECT) - * Argument "ret_cb" of LL_ASSERT() has a side effect + * Argument "ret_cb" of LL_ASSERT_ERR() has a side effect * because the variable is volatile. The containing function * might work differently in a non-debug build. */ success = (ret_cb == TICKER_STATUS_SUCCESS); - LL_ASSERT(success); + LL_ASSERT_ERR(success); /* There is a possibility that tickers expire while we * iterate through the active list of tickers, start over with @@ -478,7 +478,7 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, */ if ((ticker_id_prev != TICKER_NULL) && (*ticks_anchor != ticks_anchor_prev)) { - LL_ASSERT(retry); + LL_ASSERT_ERR(retry); retry--; ticker_id = ticker_id_prev = TICKER_NULL; diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index 0ce9658e8d24..183e8bc72bfb 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -425,8 +425,8 @@ void ull_sync_setup_from_sync_transfer(struct ll_conn *conn, uint16_t service_da (sync->ull.ticks_slot + ticks_slot_overhead), ticker_cb, sync, ticker_start_op_cb, (void *)__LINE__); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } #endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_RECEIVER */ @@ -490,7 +490,7 @@ uint8_t ll_sync_create_cancel(void **rx) if (sync->timeout_reload != 0U) { uint16_t sync_handle = ull_sync_handle_get(sync); - LL_ASSERT(sync_handle <= UINT8_MAX); + LL_ASSERT_DBG(sync_handle <= UINT8_MAX); /* Sync is not established yet, so stop sync ticker */ const int err = @@ -585,7 +585,7 @@ uint8_t ll_sync_terminate(uint16_t handle) } #if !defined(CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS) - LL_ASSERT(!aux->parent); + LL_ASSERT_DBG(!aux->parent); #endif /* !CONFIG_BT_CTLR_SCAN_AUX_USE_CHAINS */ } @@ -1153,8 +1153,8 @@ void ull_sync_setup(struct ll_scan_set *scan, uint8_t phy, (sync->ull.ticks_slot + ticks_slot_overhead), ticker_cb, sync, ticker_start_op_cb, (void *)__LINE__); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } void ull_sync_setup_reset(struct ll_sync_set *sync) @@ -1418,9 +1418,9 @@ void ull_sync_done(struct node_rx_event_done *done) ticks_drift_minus, 0, 0, lazy, force, ticker_update_op_cb, sync); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY) || - ((void *)sync == ull_disable_mark_get())); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY) || + ((void *)sync == ull_disable_mark_get())); } } } @@ -1435,7 +1435,7 @@ void ull_sync_chm_update(uint8_t sync_handle, uint8_t *acad, uint8_t acad_len) /* Get reference to LLL context */ sync = ull_sync_set_get(sync_handle); - LL_ASSERT(sync); + LL_ASSERT_DBG(sync); lll = &sync->lll; /* Ignore if already in progress */ @@ -1612,7 +1612,7 @@ static struct ll_sync_set *ull_sync_create(uint8_t sid, uint16_t timeout, uint16 /* Make sure that the node_rx_sync_establ hasn't got anything assigned. It is used to * mark when sync establishment is in progress. */ - LL_ASSERT(!sync->node_rx_sync_estab); + LL_ASSERT_DBG(!sync->node_rx_sync_estab); sync->node_rx_sync_estab = node_rx; /* Reporting initially enabled/disabled */ @@ -1659,7 +1659,7 @@ static struct ll_sync_set *ull_sync_create(uint8_t sid, uint16_t timeout, uint16 #if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX) ull_df_sync_cfg_init(&lll->df_cfg); - LL_ASSERT(!lll->node_cte_incomplete); + LL_ASSERT_DBG(!lll->node_cte_incomplete); #endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */ /* Initialise ULL and LLL headers */ @@ -1677,8 +1677,8 @@ static void sync_ticker_cleanup(struct ll_sync_set *sync, ticker_op_func stop_op /* Stop Periodic Sync Ticker */ ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH, TICKER_ID_SCAN_SYNC_BASE + sync_handle, stop_op_cb, (void *)sync); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); /* Mark sync context not sync established */ sync->timeout_reload = 0U; @@ -1706,7 +1706,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&sync->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); /* Append timing parameters */ p.ticks_at_expire = ticks_at_expire; @@ -1720,7 +1720,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0, &mfy_lll_prepare); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_PREPARE_O(1); } @@ -1728,13 +1728,13 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, static void ticker_start_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); } static void ticker_update_op_cb(uint32_t status, void *param) { - LL_ASSERT(status == TICKER_STATUS_SUCCESS || - param == ull_disable_mark_get()); + LL_ASSERT_ERR((status == TICKER_STATUS_SUCCESS) || + (param == ull_disable_mark_get())); } static void ticker_stop_sync_expire_op_cb(uint32_t status, void *param) @@ -1743,13 +1743,13 @@ static void ticker_stop_sync_expire_op_cb(uint32_t status, void *param) static memq_link_t link; static struct mayfly mfy = {0, 0, &link, NULL, sync_expire}; - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); mfy.param = param; retval = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!retval); + LL_ASSERT_ERR(!retval); } static void sync_expire(void *param) @@ -1789,7 +1789,7 @@ static void ticker_stop_sync_lost_op_cb(uint32_t status, void *param) * sync lost scenario, do not generate the sync lost node rx from here */ if (status != TICKER_STATUS_SUCCESS) { - LL_ASSERT(param == ull_disable_mark_get()); + LL_ASSERT_DBG(param == ull_disable_mark_get()); return; } @@ -1798,7 +1798,7 @@ static void ticker_stop_sync_lost_op_cb(uint32_t status, void *param) retval = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0, &mfy); - LL_ASSERT(!retval); + LL_ASSERT_ERR(!retval); } static void sync_lost(void *param) @@ -1900,8 +1900,8 @@ static struct pdu_cte_info *pdu_cte_info_get(struct pdu_adv *pdu) } /* Make sure there are no fields that are not allowed for AUX_SYNC_IND and AUX_CHAIN_IND */ - LL_ASSERT(!hdr->adv_addr); - LL_ASSERT(!hdr->tgt_addr); + LL_ASSERT_DBG(!hdr->adv_addr); + LL_ASSERT_DBG(!hdr->tgt_addr); return (struct pdu_cte_info *)hdr->data; } @@ -1956,7 +1956,7 @@ void ull_sync_transfer_received(struct ll_conn *conn, uint16_t service_data, conn_evt_current = ull_conn_event_counter(conn); /* LLCP should have ensured this holds */ - LL_ASSERT(sync_conn_event_count != conn_evt_current); + LL_ASSERT_DBG(sync_conn_event_count != conn_evt_current); ull_sync_setup_from_sync_transfer(conn, service_data, sync, si, conn_event_count - conn_evt_current, diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c index b3737c8fc4a0..de741adfd6d5 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c @@ -203,9 +203,9 @@ uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle, /* Calculate GLTK */ err = bt_crypto_h7(BIG1, bcode, igltk); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); err = bt_crypto_h6(igltk, BIG2, sync_iso->gltk); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); lll->enc = 1U; } else { @@ -309,7 +309,8 @@ uint8_t ll_big_sync_terminate(uint8_t big_handle, void **rx) mfy.param = &sync_iso->lll; ret = mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_LLL, 0, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); + k_sem_take(&sem, K_FOREVER); sync_iso->flush_sem = NULL; @@ -390,7 +391,7 @@ void ull_sync_iso_stream_release(struct ll_sync_iso_set *sync_iso) stream_handle = lll->stream_handle[lll->stream_count]; stream = ull_sync_iso_stream_get(stream_handle); - LL_ASSERT(stream); + LL_ASSERT_DBG(stream); dp = stream->dp; if (dp) { @@ -489,20 +490,22 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso, lll->irc = PDU_BIG_INFO_IRC_GET(bi); if (lll->pto) { uint8_t nse; + uint8_t ptc; nse = lll->irc * lll->bn; /* 4 bits * 3 bits, total 7 bits */ if (nse >= lll->nse) { return; } - lll->ptc = lll->nse - nse; + ptc = lll->nse - nse; /* FIXME: Do not remember why ptc is 4 bits, it should be 5 bits as ptc is a * running buffer offset related to nse. * Fix ptc and ptc_curr definitions, until then we keep an assertion check * here. */ - LL_ASSERT(lll->ptc <= BIT_MASK(4)); + LL_ASSERT_DBG(ptc <= BIT_MASK(4)); + lll->ptc = ptc; } else { lll->ptc = 0U; } @@ -532,7 +535,7 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso, /* Calculate GSK */ err = bt_crypto_h8(sync_iso->gltk, bi->gskd, BIG3, gsk); - LL_ASSERT(!err); + LL_ASSERT_DBG(!err); /* Prepare the CCM parameters */ ccm_rx = &lll->ccm_rx; @@ -584,6 +587,8 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso, lll->window_size_event_us; /* Skip to first selected BIS subevent */ stream = ull_sync_iso_stream_get(lll->stream_handle[0]); + LL_ASSERT_DBG(stream); + if (lll->bis_spacing >= (lll->sub_interval * lll->nse)) { sync_iso_offset_us += (stream->bis_index - 1U) * lll->sub_interval * @@ -705,8 +710,8 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso, (sync_iso->ull.ticks_slot + ticks_slot_overhead), ticker_cb, sync_iso, ticker_start_op_cb, (void *)__LINE__); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } void ull_sync_iso_estab_done(struct node_rx_event_done *done) @@ -843,9 +848,9 @@ void ull_sync_iso_done(struct node_rx_event_done *done) lazy, force, ticker_update_op_cb, sync_iso); - LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || - (ticker_status == TICKER_STATUS_BUSY) || - ((void *)sync_iso == ull_disable_mark_get())); + LL_ASSERT_ERR((ticker_status == TICKER_STATUS_SUCCESS) || + (ticker_status == TICKER_STATUS_BUSY) || + ((void *)sync_iso == ull_disable_mark_get())); } } @@ -995,7 +1000,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Increment prepare reference count */ ref = ull_ref_inc(&sync_iso->ull); - LL_ASSERT(ref); + LL_ASSERT_DBG(ref); /* Append timing parameters */ p.ticks_at_expire = ticks_at_expire; @@ -1008,7 +1013,7 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift, /* Kick LLL prepare */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0U, &mfy_lll_prepare); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); DEBUG_RADIO_PREPARE_O(1); } @@ -1017,13 +1022,13 @@ static void ticker_start_op_cb(uint32_t status, void *param) { ARG_UNUSED(param); - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); } static void ticker_update_op_cb(uint32_t status, void *param) { - LL_ASSERT(status == TICKER_STATUS_SUCCESS || - param == ull_disable_mark_get()); + LL_ASSERT_ERR((status == TICKER_STATUS_SUCCESS) || + (param == ull_disable_mark_get())); } static void ticker_stop_op_cb(uint32_t status, void *param) @@ -1032,13 +1037,13 @@ static void ticker_stop_op_cb(uint32_t status, void *param) static struct mayfly mfy = {0U, 0U, &link, NULL, sync_iso_disable}; uint32_t ret; - LL_ASSERT(status == TICKER_STATUS_SUCCESS); + LL_ASSERT_ERR(status == TICKER_STATUS_SUCCESS); /* Check if any pending LLL events that need to be aborted */ mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void sync_iso_disable(void *param) @@ -1059,14 +1064,14 @@ static void sync_iso_disable(void *param) /* Setup disabled callback to be called when ref count * returns to zero. */ - LL_ASSERT(!hdr->disabled_cb); + LL_ASSERT_ERR(!hdr->disabled_cb); hdr->disabled_param = mfy.param; hdr->disabled_cb = disabled_cb; /* Trigger LLL disable */ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } else { /* No pending LLL events */ disabled_cb(&sync_iso->lll); @@ -1103,7 +1108,7 @@ static void disabled_cb(void *param) /* Generate BIG sync lost */ rx = (void *)&sync_iso->node_rx_lost; - LL_ASSERT(rx->hdr.link); + LL_ASSERT_DBG(rx->hdr.link); link = rx->hdr.link; rx->hdr.link = NULL; @@ -1113,7 +1118,7 @@ static void disabled_cb(void *param) mfy.param = param; ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0U, &mfy); - LL_ASSERT(!ret); + LL_ASSERT_ERR(!ret); } static void stop_ticker(struct ll_sync_iso_set *sync_iso, ticker_op_func fp_op_func) @@ -1133,6 +1138,6 @@ static void stop_ticker(struct ll_sync_iso_set *sync_iso, ticker_op_func fp_op_f sync_iso_handle_to_index(handle), fp_op_func, fp_op_func ? (void *)sync_iso : NULL); - LL_ASSERT((ret == TICKER_STATUS_SUCCESS) || - (ret == TICKER_STATUS_BUSY)); + LL_ASSERT_ERR((ret == TICKER_STATUS_SUCCESS) || + (ret == TICKER_STATUS_BUSY)); } diff --git a/subsys/bluetooth/controller/ticker/ticker.c b/subsys/bluetooth/controller/ticker/ticker.c index 065e9981c5f0..567301756e29 100644 --- a/subsys/bluetooth/controller/ticker/ticker.c +++ b/subsys/bluetooth/controller/ticker/ticker.c @@ -1448,7 +1448,7 @@ void ticker_worker(void *param) timeout_func = ticker->ext_data->ext_timeout_func; expire_info = ticker->ext_data->other_expire_info; if (ticker->ext_data->expire_info_id != TICKER_NULL) { - LL_ASSERT(expire_info && !expire_info->outdated); + LL_ASSERT_DBG(expire_info && !expire_info->outdated); } ext_context.context = ticker->context; @@ -2327,7 +2327,7 @@ static inline uint32_t ticker_job_op_start(struct ticker_instance *instance, #if defined(CONFIG_BT_TICKER_LOW_LAT) /* Must expire is not supported in compatibility mode */ - LL_ASSERT(start->lazy < TICKER_LAZY_MUST_EXPIRE_KEEP); + LL_ASSERT_DBG(start->lazy < TICKER_LAZY_MUST_EXPIRE_KEEP); #else #if !defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC) if (start->lazy != TICKER_LAZY_MUST_EXPIRE_KEEP) { @@ -2492,7 +2492,7 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance) } /* Ensure that resched ticker is expired */ - LL_ASSERT(ticker_resched->ticks_to_expire == 0U); + LL_ASSERT_DBG(ticker_resched->ticks_to_expire == 0U); /* Use ticker's reserved time ticks_slot, else for unreserved * tickers use the reschedule margin as ticks_slot. @@ -2500,7 +2500,7 @@ static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance) if (ticker_resched->ticks_slot) { ticks_slot = ticker_resched->ticks_slot; } else { - LL_ASSERT(TICKER_HAS_SLOT_WINDOW(ticker_resched)); + LL_ASSERT_DBG(TICKER_HAS_SLOT_WINDOW(ticker_resched)); ticks_slot = HAL_TICKER_RESCHEDULE_MARGIN; } @@ -3181,7 +3181,7 @@ ticker_job_compare_update(struct ticker_instance *instance, uint32_t ticks_elapsed; uint32_t ticks_diff; - LL_ASSERT(i); + LL_ASSERT_ERR(i); i--; cc = instance->ticks_current; diff --git a/subsys/bluetooth/crypto/Kconfig b/subsys/bluetooth/crypto/Kconfig index 0856daf9d9a5..0e382060278a 100644 --- a/subsys/bluetooth/crypto/Kconfig +++ b/subsys/bluetooth/crypto/Kconfig @@ -3,11 +3,11 @@ config BT_CRYPTO bool - select MBEDTLS if !BUILD_WITH_TFM - select MBEDTLS_PSA_CRYPTO_C if !BUILD_WITH_TFM + select PSA_CRYPTO select PSA_WANT_KEY_TYPE_AES select PSA_WANT_ALG_CMAC select PSA_WANT_ALG_ECB_NO_PADDING + imply MBEDTLS_CIPHER_AES_ENABLED if !BUILD_WITH_TFM imply MBEDTLS_AES_ROM_TABLES if MBEDTLS_PSA_CRYPTO_C help This option enables the Bluetooth Cryptographic Toolbox. diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 72deb4343dc4..0d0bfd20a883 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -111,6 +111,7 @@ config BT_RX_STACK_SIZE int "Size of the receiving thread stack" default 768 if BT_HCI_RAW default 3092 if BT_MESH_GATT_CLIENT + default 2800 if BT_MESH_PB_GATT default 2600 if BT_MESH default 2048 if BT_AUDIO default 1200 @@ -200,8 +201,7 @@ config BT_BUF_EVT_DISCARDABLE_COUNT config BT_HOST_CRYPTO bool "Use crypto functionality implemented in the Bluetooth host" default y if !BT_CTLR_CRYPTO - select MBEDTLS if !BUILD_WITH_TFM - select MBEDTLS_PSA_CRYPTO_C if !BUILD_WITH_TFM + select PSA_CRYPTO select PSA_WANT_KEY_TYPE_AES select PSA_WANT_ALG_ECB_NO_PADDING help @@ -658,6 +658,24 @@ config BT_ID_UNPAIR_MATCHING_BONDS link-layer. The Host does not have control over this acknowledgment, and the order of distribution is fixed by the specification. +config BT_ID_AUTO_SWAP_MATCHING_BONDS + bool "Automatically swap conflicting entries in the Resolving List" + depends on !BT_ID_UNPAIR_MATCHING_BONDS + depends on BT_SMP && BT_PERIPHERAL && !BT_CENTRAL + help + If this option is enabled, the Host will not add a new bond with + the same peer address (or IRK) to the Resolving List if there is + already a bond with the same peer address (or IRK) on another local + identity. + + In case of Peripheral, the Host will swap the existing entry in the + Resolving List with the new one, so that the new bond will be used for + address resolution for the new local identity if the device starts + advertising with the new local identity. + + Important: this option is supported exclusively in the Peripheral + role. Excluding the Central role. + config BT_ID_ALLOW_UNAUTH_OVERWRITE bool "Allow unauthenticated pairing with same peer with other local identity" depends on !BT_SMP_ALLOW_UNAUTH_OVERWRITE @@ -683,12 +701,24 @@ config BT_SMP_USB_HCI_CTLR_WORKAROUND if the keys are distributed over an encrypted link. config BT_FIXED_PASSKEY - bool "Use a fixed passkey for pairing" + bool "Use a fixed passkey for pairing [DEPRECATED]" + select DEPRECATED help + This option is deprecated, use BT_APP_PASSKEY instead. With this option enabled, the application will be able to call the bt_passkey_set() API to set a fixed passkey. If set, the pairing_confirm() callback will be called for all incoming pairings. +config BT_APP_PASSKEY + bool "Allow the application to provide passkeys for pairing" + depends on !BT_FIXED_PASSKEY + help + With this option enabled, the application will be able to provide passkeys for pairing + using the app_passkey() callback. If the application does not provide a passkey, a + random passkey will be generated by the Host. + + WARNING: It is the responsibility of the application to use random and unique keys. + config BT_USE_DEBUG_KEYS bool "Security Manager Debug Mode" help @@ -1023,8 +1053,7 @@ endif # BT_DF config BT_ECC bool - select MBEDTLS if !BUILD_WITH_TFM - select MBEDTLS_PSA_CRYPTO_C if !BUILD_WITH_TFM + select PSA_CRYPTO select PSA_WANT_ALG_ECDH select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT diff --git a/subsys/bluetooth/host/Kconfig.gatt b/subsys/bluetooth/host/Kconfig.gatt index a04241a3e94f..3403e8d308b8 100644 --- a/subsys/bluetooth/host/Kconfig.gatt +++ b/subsys/bluetooth/host/Kconfig.gatt @@ -38,6 +38,20 @@ config BT_ATT_RETRY_ON_SEC_ERR If an ATT request fails due to insufficient security, the host will try to elevate the security level and retry the ATT request. +config BT_ATT_SENT_CB_AFTER_TX + bool "Delay ATT sent callback until data transmission is done by controller [EXPERIMENTAL]" + select EXPERIMENTAL + help + By default, the BLE stack calls sent callback for ATT data when the + data is passed to BLE controller for transmission. Enabling this + Kconfig option delays calling the sent callback until data + transmission is finished by BLE controller (the callback is called + upon receiving the Number of Completed Packets HCI Event). + + The feature is not available in Zephyr RTOS (it's specific to NCS + Zephyr fork). It is a temporary solution allowing to control flow of + GATT notifications with HID reports for HID use-case. + config BT_EATT bool "Enhanced ATT Bearers support [EXPERIMENTAL]" depends on BT_L2CAP_ECRED diff --git a/subsys/bluetooth/host/Kconfig.l2cap b/subsys/bluetooth/host/Kconfig.l2cap index 2841e7d8a129..34e862378c5e 100644 --- a/subsys/bluetooth/host/Kconfig.l2cap +++ b/subsys/bluetooth/host/Kconfig.l2cap @@ -52,7 +52,7 @@ config BT_L2CAP_DYNAMIC_CHANNEL allowing the creation of dynamic L2CAP Channels. config BT_L2CAP_ECRED - bool "L2CAP Enhanced Credit Based Flow Control support" + bool "L2CAP Enhanced Credit Based Flow Control support [EXPERIMENTAL]" depends on BT_L2CAP_DYNAMIC_CHANNEL help This option enables support for LE Connection oriented Channels with diff --git a/subsys/bluetooth/host/adv.c b/subsys/bluetooth/host/adv.c index 749495bcb563..3a17a7192535 100644 --- a/subsys/bluetooth/host/adv.c +++ b/subsys/bluetooth/host/adv.c @@ -34,6 +34,7 @@ #include "hci_core.h" #include "id.h" #include "scan.h" +#include "adv.h" #define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL LOG_MODULE_REGISTER(bt_adv); @@ -187,11 +188,9 @@ static struct bt_le_ext_adv adv_pool[CONFIG_BT_EXT_ADV_MAX_ADV_SET]; #if defined(CONFIG_BT_EXT_ADV) uint8_t bt_le_ext_adv_get_index(struct bt_le_ext_adv *adv) { - ptrdiff_t index = adv - adv_pool; + __ASSERT(IS_ARRAY_ELEMENT(adv_pool, adv), "Invalid bt_adv pointer"); - __ASSERT(index >= 0 && index < ARRAY_SIZE(adv_pool), - "Invalid bt_adv pointer"); - return (uint8_t)index; + return (uint8_t)ARRAY_INDEX(adv_pool, adv); } static struct bt_le_ext_adv *adv_new(void) @@ -235,6 +234,25 @@ struct bt_le_ext_adv *bt_hci_adv_lookup_handle(uint8_t handle) #endif /* CONFIG_BT_BROADCASTER */ #endif /* defined(CONFIG_BT_EXT_ADV) */ +struct bt_le_ext_adv *bt_adv_lookup_by_id(uint8_t id) +{ +#if defined(CONFIG_BT_EXT_ADV) + for (size_t i = 0; i < ARRAY_SIZE(adv_pool); i++) { + if (atomic_test_bit(adv_pool[i].flags, BT_ADV_CREATED) && + adv_pool[i].id == id) { + return &adv_pool[i]; + } + } +#else + if (atomic_test_bit(bt_dev.adv.flags, BT_ADV_CREATED) && bt_dev.adv.id == id) { + return &bt_dev.adv; + } +#endif + + return NULL; +} + + void bt_le_ext_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data), void *data) { @@ -249,12 +267,15 @@ void bt_le_ext_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data), #endif /* defined(CONFIG_BT_EXT_ADV) */ } -void bt_adv_reset_adv_pool(void) +static void clear_ext_adv_instance(struct bt_le_ext_adv *adv, void *data) { -#if defined(CONFIG_BT_EXT_ADV) - (void)memset(&adv_pool, 0, sizeof(adv_pool)); -#endif /* defined(CONFIG_BT_EXT_ADV) */ + bt_le_lim_adv_cancel_timeout(adv); + memset(adv, 0, sizeof(*adv)); +} +void bt_adv_reset_adv_pool(void) +{ + bt_le_ext_adv_foreach(clear_ext_adv_instance, NULL); (void)memset(&bt_dev.adv, 0, sizeof(bt_dev.adv)); } @@ -368,9 +389,8 @@ static bool valid_adv_ext_param(const struct bt_le_adv_param *param) { if (IS_ENABLED(CONFIG_BT_EXT_ADV) && BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - if (param->peer && - !(param->options & BT_LE_ADV_OPT_EXT_ADV) && - !(param->options & _BT_LE_ADV_OPT_CONNECTABLE)) { + if (param->peer && !(param->options & BT_LE_ADV_OPT_EXT_ADV) && + !(param->options & BT_LE_ADV_OPT_CONN)) { /* Cannot do directed non-connectable advertising * without extended advertising. */ @@ -410,7 +430,7 @@ static bool valid_adv_ext_param(const struct bt_le_adv_param *param) return false; } - if (!(param->options & _BT_LE_ADV_OPT_CONNECTABLE)) { + if (!(param->options & BT_LE_ADV_OPT_CONN)) { /* * BT Core 4.2 [Vol 2, Part E, 7.8.5] * The Advertising_Interval_Min and Advertising_Interval_Max @@ -453,7 +473,7 @@ static bool valid_adv_param(const struct bt_le_adv_param *param) return false; } - if (param->peer && !(param->options & _BT_LE_ADV_OPT_CONNECTABLE)) { + if (param->peer && !(param->options & BT_LE_ADV_OPT_CONN)) { return false; } @@ -928,6 +948,14 @@ static int adv_start_legacy(struct bt_le_ext_adv *adv, adv->id = param->id; bt_dev.adv_conn_id = adv->id; + if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + err = bt_id_resolving_list_check_and_update(adv->id, param->peer); + if (err) { + LOG_ERR("Failed to check and update resolving list: %d", err); + return err; + } + } + err = bt_id_set_adv_own_addr(adv, param->options, dir_adv, &set_param.own_addr_type); if (err) { @@ -940,7 +968,7 @@ static int adv_start_legacy(struct bt_le_ext_adv *adv, bt_addr_le_copy(&adv->target_addr, BT_ADDR_LE_ANY); } - if (param->options & _BT_LE_ADV_OPT_CONNECTABLE) { + if (param->options & BT_LE_ADV_OPT_CONN) { if (dir_adv) { if (param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) { set_param.type = BT_HCI_ADV_DIRECT_IND_LOW_DUTY; @@ -979,15 +1007,9 @@ static int adv_start_legacy(struct bt_le_ext_adv *adv, } } - if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && - (param->options & _BT_LE_ADV_OPT_CONNECTABLE)) { + if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && (param->options & BT_LE_ADV_OPT_CONN)) { err = le_adv_start_add_conn(adv, &conn); if (err) { - if (err == -ENOMEM && !dir_adv && - !(param->options & _BT_LE_ADV_OPT_ONE_TIME)) { - goto set_adv_state; - } - return err; } } @@ -1012,12 +1034,7 @@ static int adv_start_legacy(struct bt_le_ext_adv *adv, bt_conn_unref(conn); } -set_adv_state: - atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, !dir_adv && - !(param->options & _BT_LE_ADV_OPT_ONE_TIME)); - - atomic_set_bit_to(adv->flags, BT_ADV_CONNECTABLE, - param->options & _BT_LE_ADV_OPT_CONNECTABLE); + atomic_set_bit_to(adv->flags, BT_ADV_CONNECTABLE, param->options & BT_LE_ADV_OPT_CONN); atomic_set_bit_to(adv->flags, BT_ADV_SCANNABLE, scannable); @@ -1125,7 +1142,7 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv, cp->scan_req_notify_enable = BT_HCI_LE_ADV_SCAN_REQ_ENABLE; } - if (param->options & _BT_LE_ADV_OPT_CONNECTABLE) { + if (param->options & BT_LE_ADV_OPT_CONN) { props |= BT_HCI_LE_ADV_PROP_CONN; if (!dir_adv && !(param->options & BT_LE_ADV_OPT_EXT_ADV)) { /* When using non-extended adv packets then undirected @@ -1180,11 +1197,7 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv, } } - /* Flag only used by bt_le_adv_start API. */ - atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, false); - - atomic_set_bit_to(adv->flags, BT_ADV_CONNECTABLE, - param->options & _BT_LE_ADV_OPT_CONNECTABLE); + atomic_set_bit_to(adv->flags, BT_ADV_CONNECTABLE, param->options & BT_LE_ADV_OPT_CONN); atomic_set_bit_to(adv->flags, BT_ADV_SCANNABLE, scannable); @@ -1194,6 +1207,9 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv, atomic_set_bit_to(adv->flags, BT_ADV_EXT_ADV, param->options & BT_LE_ADV_OPT_EXT_ADV); + atomic_set_bit_to(adv->flags, BT_ADV_RANDOM_ADDR_UPDATED, + own_addr_type == BT_HCI_OWN_ADDR_RANDOM); + return 0; } @@ -1223,6 +1239,15 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv, } adv->id = param->id; + + if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + err = bt_id_resolving_list_check_and_update(adv->id, param->peer); + if (err) { + LOG_ERR("Failed to check and update resolving list: %d", err); + return err; + } + } + err = le_ext_adv_param_set(adv, param, sd != NULL); if (err) { return err; @@ -1243,15 +1268,9 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv, } } - if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && - (param->options & _BT_LE_ADV_OPT_CONNECTABLE)) { + if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && (param->options & BT_LE_ADV_OPT_CONN)) { err = le_adv_start_add_conn(adv, &conn); if (err) { - if (err == -ENOMEM && !dir_adv && - !(param->options & _BT_LE_ADV_OPT_ONE_TIME)) { - goto set_adv_state; - } - return err; } } @@ -1276,11 +1295,6 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv, bt_conn_unref(conn); } -set_adv_state: - /* Flag always set to false by le_ext_adv_param_set */ - atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, !dir_adv && - !(param->options & _BT_LE_ADV_OPT_ONE_TIME)); - return 0; } @@ -1337,11 +1351,6 @@ int bt_le_adv_stop(void) (void)bt_le_lim_adv_cancel_timeout(adv); - /* Make sure advertising is not re-enabled later even if it's not - * currently enabled (i.e. BT_DEV_ADVERTISING is not set). - */ - atomic_clear_bit(adv->flags, BT_ADV_PERSIST); - if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { /* Legacy advertiser exists, but is not currently advertising. * This happens when keep advertising behavior is active but @@ -1388,93 +1397,6 @@ int bt_le_adv_stop(void) return 0; } -#if defined(CONFIG_BT_PERIPHERAL) -static uint32_t adv_get_options(const struct bt_le_ext_adv *adv) -{ - uint32_t options = 0; - - if (!atomic_test_bit(adv->flags, BT_ADV_PERSIST)) { - options |= _BT_LE_ADV_OPT_ONE_TIME; - } - - if (atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { - options |= _BT_LE_ADV_OPT_CONNECTABLE; - } - - if (atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { - options |= BT_LE_ADV_OPT_USE_IDENTITY; - } - - return options; -} - -void bt_le_adv_resume(void) -{ - struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy(); - struct bt_conn *conn; - bool persist_paused = false; - int err; - - if (!adv) { - LOG_DBG("No valid legacy adv to resume"); - return; - } - - if (!(atomic_test_bit(adv->flags, BT_ADV_PERSIST) && - !atomic_test_bit(adv->flags, BT_ADV_ENABLED))) { - return; - } - - if (!atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { - return; - } - - err = le_adv_start_add_conn(adv, &conn); - if (err) { - LOG_ERR("Host cannot resume connectable advertising (%d)", err); - return; - } - - LOG_DBG("Resuming connectable advertising"); - - if (IS_ENABLED(CONFIG_BT_PRIVACY) && - !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { - bt_id_set_adv_private_addr(adv); - } else { - uint8_t own_addr_type; - bool dir_adv = adv_is_directed(adv); - uint32_t options = adv_get_options(adv); - - /* Always set the address. Don't assume it has not changed. */ - err = bt_id_set_adv_own_addr(adv, options, dir_adv, &own_addr_type); - if (err) { - LOG_ERR("Controller cannot resume connectable advertising (%d)", err); - return; - } - } - - err = bt_le_adv_set_enable(adv, true); - if (err) { - LOG_ERR("Controller cannot resume connectable advertising (%d)", err); - bt_conn_set_state(conn, BT_CONN_DISCONNECTED); - - /* Temporarily clear persist flag to avoid recursion in - * bt_conn_unref if the flag is still set. - */ - persist_paused = atomic_test_and_clear_bit(adv->flags, - BT_ADV_PERSIST); - } - - /* Since we don't give the application a reference to manage in - * this case, we need to release this reference here. - */ - bt_conn_unref(conn); - if (persist_paused) { - atomic_set_bit(adv->flags, BT_ADV_PERSIST); - } -} -#endif /* defined(CONFIG_BT_PERIPHERAL) */ - #if defined(CONFIG_BT_EXT_ADV) int bt_le_ext_adv_get_info(const struct bt_le_ext_adv *adv, struct bt_le_ext_adv_info *info) @@ -1578,7 +1500,7 @@ int bt_le_ext_adv_update_param(struct bt_le_ext_adv *adv, /* If params for per adv has been set, do not allow setting * connectable, scanable or use legacy adv */ - if (param->options & _BT_LE_ADV_OPT_CONNECTABLE || + if (param->options & BT_LE_ADV_OPT_CONN || param->options & BT_LE_ADV_OPT_SCANNABLE || !(param->options & BT_LE_ADV_OPT_EXT_ADV) || param->options & BT_LE_ADV_OPT_ANONYMOUS) { @@ -1613,6 +1535,22 @@ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv, return -EALREADY; } + if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + const bt_addr_le_t *peer; + + if (bt_addr_le_eq(&adv->target_addr, BT_ADDR_LE_ANY)) { + peer = NULL; + } else { + peer = &adv->target_addr; + } + + err = bt_id_resolving_list_check_and_update(adv->id, peer); + if (err) { + LOG_ERR("Failed to check and update resolving list: %d", err); + return err; + } + } + if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { err = le_adv_start_add_conn(adv, &conn); @@ -1626,11 +1564,15 @@ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv, if (atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { if (IS_ENABLED(CONFIG_BT_PRIVACY) && - !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { + !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && + (!atomic_test_and_clear_bit(adv->flags, BT_ADV_RANDOM_ADDR_UPDATED) || + atomic_test_bit(adv->flags, BT_PER_ADV_ENABLED))) { bt_id_set_adv_private_addr(adv); } } else { - if (!atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) { + if (!atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) && + (!atomic_test_and_clear_bit(adv->flags, BT_ADV_RANDOM_ADDR_UPDATED) || + atomic_test_bit(adv->flags, BT_PER_ADV_ENABLED))) { bt_id_set_adv_private_addr(adv); } } @@ -1668,8 +1610,6 @@ int bt_le_ext_adv_stop(struct bt_le_ext_adv *adv) (void)bt_le_lim_adv_cancel_timeout(adv); - atomic_clear_bit(adv->flags, BT_ADV_PERSIST); - if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { return 0; } @@ -2272,13 +2212,7 @@ void bt_hci_le_adv_set_terminated(struct net_buf *buf) } if (adv == bt_dev.adv) { - if (atomic_test_bit(adv->flags, BT_ADV_PERSIST)) { -#if defined(CONFIG_BT_PERIPHERAL) - bt_le_adv_resume(); -#endif - } else { - bt_le_adv_delete_legacy(); - } + bt_le_adv_delete_legacy(); } } diff --git a/subsys/bluetooth/host/adv.h b/subsys/bluetooth/host/adv.h index 65ad51135ce0..a6f7007f64b4 100644 --- a/subsys/bluetooth/host/adv.h +++ b/subsys/bluetooth/host/adv.h @@ -9,8 +9,6 @@ #include -void bt_le_adv_resume(void); - struct bt_le_ext_adv *bt_le_adv_lookup_legacy(void); void bt_le_adv_delete_legacy(void); @@ -25,3 +23,4 @@ int bt_le_adv_set_enable_ext(struct bt_le_ext_adv *adv, int bt_le_adv_set_enable_legacy(struct bt_le_ext_adv *adv, bool enable); int bt_le_lim_adv_cancel_timeout(struct bt_le_ext_adv *adv); void bt_adv_reset_adv_pool(void); +struct bt_le_ext_adv *bt_adv_lookup_by_id(uint8_t id); diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index 82d82526b5b0..c822de7ab4bc 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -143,11 +143,6 @@ static uint16_t bt_att_mtu(struct bt_att_chan *chan) return MIN(chan->chan.rx.mtu, chan->chan.tx.mtu); } -/* Descriptor of application-specific authorization callbacks that are used - * with the CONFIG_BT_GATT_AUTHORIZATION_CUSTOM Kconfig enabled. - */ -static const struct bt_gatt_authorization_cb *authorization_cb; - /* ATT connection specific data */ struct bt_att { struct bt_conn *conn; @@ -328,6 +323,13 @@ static void att_disconnect(struct bt_att_chan *chan) } } +static void chan_sent_cb(struct bt_conn *conn, void *user_data, int err) +{ + struct net_buf *nb = user_data; + + net_buf_unref(nb); +} + /* In case of success the ownership of the buffer is transferred to the stack * which takes care of releasing it when it completes transmitting to the * controller. @@ -421,7 +423,15 @@ static int chan_send(struct bt_att_chan *chan, struct net_buf *buf) data->att_chan = chan; - err = bt_l2cap_send_pdu(&chan->chan, buf, NULL, NULL); + if (IS_ENABLED(CONFIG_BT_ATT_SENT_CB_AFTER_TX)) { + err = bt_l2cap_send_pdu(&chan->chan, buf, chan_sent_cb, net_buf_ref(buf)); + if (err) { + net_buf_unref(buf); + } + } else { + err = bt_l2cap_send_pdu(&chan->chan, buf, NULL, NULL); + } + if (err) { if (err == -ENOBUFS) { LOG_ERR("Ran out of TX buffers or contexts."); @@ -1350,20 +1360,6 @@ struct read_type_data { typedef bool (*attr_read_cb)(struct net_buf *buf, ssize_t read, void *user_data); -static bool attr_read_authorize(struct bt_conn *conn, - const struct bt_gatt_attr *attr) -{ - if (!IS_ENABLED(CONFIG_BT_GATT_AUTHORIZATION_CUSTOM)) { - return true; - } - - if (!authorization_cb || !authorization_cb->read_authorize) { - return true; - } - - return authorization_cb->read_authorize(conn, attr); -} - static bool attr_read_type_cb(struct net_buf *frag, ssize_t read, void *user_data) { @@ -1474,7 +1470,7 @@ static uint8_t read_type_cb(const struct bt_gatt_attr *attr, uint16_t handle, } /* Check the attribute authorization logic */ - if (!attr_read_authorize(conn, attr)) { + if (!bt_gatt_attr_read_authorize(conn, attr)) { data->err = BT_ATT_ERR_AUTHORIZATION; return BT_GATT_ITER_STOP; } @@ -1630,7 +1626,7 @@ static uint8_t read_cb(const struct bt_gatt_attr *attr, uint16_t handle, } /* Check the attribute authorization logic */ - if (!attr_read_authorize(conn, attr)) { + if (!bt_gatt_attr_read_authorize(conn, attr)) { data->err = BT_ATT_ERR_AUTHORIZATION; return BT_GATT_ITER_STOP; } @@ -1801,7 +1797,7 @@ static uint8_t read_vl_cb(const struct bt_gatt_attr *attr, uint16_t handle, } /* Check the attribute authorization logic */ - if (!attr_read_authorize(conn, attr)) { + if (!bt_gatt_attr_read_authorize(conn, attr)) { data->err = BT_ATT_ERR_AUTHORIZATION; return BT_GATT_ITER_STOP; } @@ -2050,20 +2046,6 @@ struct write_data { uint8_t err; }; -static bool attr_write_authorize(struct bt_conn *conn, - const struct bt_gatt_attr *attr) -{ - if (!IS_ENABLED(CONFIG_BT_GATT_AUTHORIZATION_CUSTOM)) { - return true; - } - - if (!authorization_cb || !authorization_cb->write_authorize) { - return true; - } - - return authorization_cb->write_authorize(conn, attr); -} - static uint8_t write_cb(const struct bt_gatt_attr *attr, uint16_t handle, void *user_data) { @@ -2081,7 +2063,7 @@ static uint8_t write_cb(const struct bt_gatt_attr *attr, uint16_t handle, } /* Check the attribute authorization logic */ - if (!attr_write_authorize(data->conn, attr)) { + if (!bt_gatt_attr_write_authorize(data->conn, attr)) { data->err = BT_ATT_ERR_AUTHORIZATION; return BT_GATT_ITER_STOP; } @@ -2200,7 +2182,7 @@ static uint8_t prep_write_cb(const struct bt_gatt_attr *attr, uint16_t handle, } /* Check the attribute authorization logic */ - if (!attr_write_authorize(data->conn, attr)) { + if (!bt_gatt_attr_write_authorize(data->conn, attr)) { data->err = BT_ATT_ERR_AUTHORIZATION; return BT_GATT_ITER_STOP; } @@ -3522,7 +3504,10 @@ static int bt_att_accept(struct bt_conn *conn, struct bt_l2cap_chan **ch) * placed as the last one to ensure that SMP channel is properly initialized before bt_att_connected * tries to send security request. */ -BT_L2CAP_CHANNEL_DEFINE(z_att_fixed_chan, BT_L2CAP_CID_ATT, bt_att_accept, NULL); +BT_L2CAP_FIXED_CHANNEL_DEFINE(z_att_fixed_chan) = { + .cid = BT_L2CAP_CID_ATT, + .accept = bt_att_accept, +}; #if defined(CONFIG_BT_EATT) static k_timeout_t credit_based_connection_delay(struct bt_conn *conn) @@ -4169,23 +4154,3 @@ bool bt_att_chan_opt_valid(struct bt_conn *conn, enum bt_att_chan_opt chan_opt) return true; } - -int bt_gatt_authorization_cb_register(const struct bt_gatt_authorization_cb *cb) -{ - if (!IS_ENABLED(CONFIG_BT_GATT_AUTHORIZATION_CUSTOM)) { - return -ENOSYS; - } - - if (!cb) { - authorization_cb = NULL; - return 0; - } - - if (authorization_cb) { - return -EALREADY; - } - - authorization_cb = cb; - - return 0; -} diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index f3abf67d4fb6..e706fd3fb934 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -711,12 +711,29 @@ static int send_buf(struct bt_conn *conn, struct net_buf *buf, uint16_t frag_len = MIN(conn_mtu(conn), len); - /* Check that buf->ref is 1 or 2. It would be 1 if this - * was the only reference (e.g. buf was removed - * from the conn tx_queue). It would be 2 if the - * tx_data_pull kept it on the tx_queue for segmentation. + /* If ATT sent callback is delayed until data transmission + * is done by BLE controller (CONFIG_BT_ATT_SENT_CB_AFTER_TX), + * the `chan_send` function from `att.c` introduces an additional + * reference. The reference is used to extend lifetime of the net + * buffer until the data transmission is confirmed by ACK of the + * remote (the reference is removed when the TX callback passed + * to `bt_l2cap_send_pdu` is called). + * + * send_buf function can be called multiple times, if buffer + * has to be fragmented over HCI. In that case, the callback + * is provided as an argument only for the last transmitted + * fragment. The `buf->ref == 1` (or 2) check is skipped + * because it's impossible to properly validate number of + * references for the sent fragments if buffers may have the + * additional reference. + * + * Otherwise, check that buf->ref is 1 or 2. It would be 1 + * if this was the only reference (e.g. buf was removed from + * the conn tx_queue). It would be 2 if the tx_data_pull + * kept it on the tx_queue for segmentation. */ - __ASSERT_NO_MSG((buf->ref == 1) || (buf->ref == 2)); + __ASSERT_NO_MSG(IS_ENABLED(CONFIG_BT_ATT_SENT_CB_AFTER_TX) || (buf->ref == 1) || + (buf->ref == 2)); /* The reference is always transferred to the frag, so when * the frag is destroyed, the parent reference is decremented. @@ -1051,7 +1068,7 @@ void bt_conn_tx_processor(void) LOG_DBG("processing conn %p", conn); if (conn->state != BT_CONN_CONNECTED) { - LOG_WRN("conn %p: not connected", conn); + LOG_DBG("conn %p: not connected: state %d", conn, conn->state); goto raise_and_exit; } @@ -1497,43 +1514,46 @@ void bt_conn_unref(struct bt_conn *conn) { atomic_val_t old; bool deallocated; - enum bt_conn_type conn_type; - uint8_t conn_role; uint16_t conn_handle; + /* Used only if CONFIG_ASSERT and CONFIG_BT_CONN_TX. */ + __maybe_unused bool conn_tx_is_pending; __ASSERT(conn, "Invalid connection reference"); - /* Storing parameters of interest so we don't access the object - * after decrementing its ref-count + /* If we're removing the last reference, the connection object will be + * considered freed and possibly re-allocated by the Bluetooth Host stack + * as soon as we decrement the counter. + * To prevent inconsistencies when accessing the connection's state, + * we store its properties of interest before decrementing the ref-count, + * then unset the local pointer. */ - conn_type = conn->type; - conn_role = conn->role; conn_handle = conn->handle; - +#if CONFIG_BT_CONN_TX && CONFIG_ASSERT + conn_tx_is_pending = k_work_is_pending(&conn->tx_complete_work); +#endif old = atomic_dec(&conn->ref); - /* Prevent from accessing connection object */ - deallocated = (atomic_get(&old) == 1); - IF_ENABLED(CONFIG_BT_CONN_TX, - (__ASSERT(!(deallocated && k_work_is_pending(&conn->tx_complete_work)), - "tx_complete_work is pending when conn is deallocated"))); conn = NULL; LOG_DBG("handle %u ref %ld -> %ld", conn_handle, old, (old - 1)); __ASSERT(old > 0, "Conn reference counter is 0"); - /* Slot has been freed and can be taken. No guarantees are made on requests - * to claim connection object as only the first claim will be served. - */ - if (deallocated) { - k_sem_give(&pending_recycled_events); - k_work_submit(&recycled_work); + /* Whether we removed the last reference. */ + deallocated = (old == 1); + if (!deallocated) { + return; } - if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn_type == BT_CONN_TYPE_LE && - conn_role == BT_CONN_ROLE_PERIPHERAL && deallocated) { - bt_le_adv_resume(); - } + IF_ENABLED(CONFIG_BT_CONN_TX, + (__ASSERT(!conn_tx_is_pending, + "tx_complete_work is pending when conn is deallocated");)) + + /* Notify listeners that a slot has been freed and can be taken. + * No guarantees are made on requests to claim connection object + * as only the first claim will be served. + */ + k_sem_give(&pending_recycled_events); + k_work_submit(&recycled_work); } uint8_t bt_conn_index(const struct bt_conn *conn) @@ -1543,23 +1563,20 @@ uint8_t bt_conn_index(const struct bt_conn *conn) switch (conn->type) { #if defined(CONFIG_BT_ISO) case BT_CONN_TYPE_ISO: - index = conn - iso_conns; - __ASSERT(index >= 0 && index < ARRAY_SIZE(iso_conns), - "Invalid bt_conn pointer"); + __ASSERT(IS_ARRAY_ELEMENT(iso_conns, conn), "Invalid bt_conn pointer"); + index = ARRAY_INDEX(iso_conns, conn); break; #endif #if defined(CONFIG_BT_CLASSIC) case BT_CONN_TYPE_SCO: - index = conn - sco_conns; - __ASSERT(index >= 0 && index < ARRAY_SIZE(sco_conns), - "Invalid bt_conn pointer"); + __ASSERT(IS_ARRAY_ELEMENT(sco_conns, conn), "Invalid bt_conn pointer"); + index = ARRAY_INDEX(sco_conns, conn); break; #endif default: #if defined(CONFIG_BT_CONN) - index = conn - acl_conns; - __ASSERT(index >= 0 && index < ARRAY_SIZE(acl_conns), - "Invalid bt_conn pointer"); + __ASSERT(IS_ARRAY_ELEMENT(acl_conns, conn), "Invalid bt_conn pointer"); + index = ARRAY_INDEX(acl_conns, conn); #else __ASSERT(false, "Invalid connection type %u", conn->type); #endif /* CONFIG_BT_CONN */ @@ -2232,7 +2249,10 @@ static void deferred_work(struct k_work *work) * auto connect flag if it was set, instead just cancel * connection directly */ - bt_le_create_conn_cancel(); + if (bt_le_create_conn_cancel() == -ENOBUFS) { + LOG_WRN("No buffers to cancel connection, retrying in 10 ms"); + k_work_reschedule(dwork, K_MSEC(10)); + } return; } @@ -2272,6 +2292,10 @@ static void deferred_work(struct k_work *work) err); } #endif + } else { + /* Neither the application nor the configuration + * set LE connection parameters. + */ } atomic_set_bit(conn->flags, BT_CONN_PERIPHERAL_PARAM_UPDATE); @@ -2374,6 +2398,8 @@ struct bt_conn *bt_conn_add_sco(const bt_addr_t *peer, int link_type) } else if (link_type == BT_HCI_ESCO) { sco_conn->sco.pkt_type = (bt_dev.br.esco_pkt_type & ~EDR_ESCO_PKT_MASK); + } else { + /* Ignoring unexpected link type BT_HCI_ACL. */ } return sco_conn; @@ -3966,65 +3992,6 @@ int bt_conn_le_create_synced(const struct bt_le_ext_adv *adv, *ret_conn = conn; return 0; } - -#if !defined(CONFIG_BT_FILTER_ACCEPT_LIST) -int bt_le_set_auto_conn(const bt_addr_le_t *addr, - const struct bt_le_conn_param *param) -{ - struct bt_conn *conn; - - if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - return -EAGAIN; - } - - if (param && !bt_le_conn_params_valid(param)) { - return -EINVAL; - } - - if (!bt_id_scan_random_addr_check()) { - return -EINVAL; - } - - /* Only default identity is supported */ - conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr); - if (!conn) { - conn = bt_conn_add_le(BT_ID_DEFAULT, addr); - if (!conn) { - return -ENOMEM; - } - } - - if (param) { - bt_conn_set_param_le(conn, param); - - if (!atomic_test_and_set_bit(conn->flags, - BT_CONN_AUTO_CONNECT)) { - bt_conn_ref(conn); - } - } else { - if (atomic_test_and_clear_bit(conn->flags, - BT_CONN_AUTO_CONNECT)) { - bt_conn_unref(conn); - if (conn->state == BT_CONN_SCAN_BEFORE_INITIATING) { - bt_conn_set_state(conn, BT_CONN_DISCONNECTED); - } - } - } - - int err = 0; - if (conn->state == BT_CONN_DISCONNECTED && - atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { - if (param) { - bt_conn_set_state(conn, BT_CONN_SCAN_BEFORE_INITIATING); - err = bt_le_scan_user_add(BT_LE_SCAN_USER_CONN); - } - } - - bt_conn_unref(conn); - - return err; -} -#endif /* !defined(CONFIG_BT_FILTER_ACCEPT_LIST) */ #endif /* CONFIG_BT_CENTRAL */ int bt_conn_le_conn_update(struct bt_conn *conn, diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 0770d6a407bb..ea1dc73e158a 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -6590,3 +6590,54 @@ void bt_gatt_req_set_mtu(struct bt_att_req *req, uint16_t mtu) * request types if needed. */ } + +/* Descriptor of application-specific authorization callbacks that are used + * with the CONFIG_BT_GATT_AUTHORIZATION_CUSTOM Kconfig enabled. + */ +static const struct bt_gatt_authorization_cb *authorization_cb; + +bool bt_gatt_attr_read_authorize(struct bt_conn *conn, const struct bt_gatt_attr *attr) +{ + if (!IS_ENABLED(CONFIG_BT_GATT_AUTHORIZATION_CUSTOM)) { + return true; + } + + if (!authorization_cb || !authorization_cb->read_authorize) { + return true; + } + + return authorization_cb->read_authorize(conn, attr); +} + +bool bt_gatt_attr_write_authorize(struct bt_conn *conn, const struct bt_gatt_attr *attr) +{ + if (!IS_ENABLED(CONFIG_BT_GATT_AUTHORIZATION_CUSTOM)) { + return true; + } + + if (!authorization_cb || !authorization_cb->write_authorize) { + return true; + } + + return authorization_cb->write_authorize(conn, attr); +} + +int bt_gatt_authorization_cb_register(const struct bt_gatt_authorization_cb *cb) +{ + if (!IS_ENABLED(CONFIG_BT_GATT_AUTHORIZATION_CUSTOM)) { + return -ENOSYS; + } + + if (!cb) { + authorization_cb = NULL; + return 0; + } + + if (authorization_cb) { + return -EALREADY; + } + + authorization_cb = cb; + + return 0; +} diff --git a/subsys/bluetooth/host/gatt_internal.h b/subsys/bluetooth/host/gatt_internal.h index 1dab30471af1..dbe3736cb0fc 100644 --- a/subsys/bluetooth/host/gatt_internal.h +++ b/subsys/bluetooth/host/gatt_internal.h @@ -68,3 +68,6 @@ struct bt_gatt_attr; /* Check attribute permission */ uint8_t bt_gatt_check_perm(struct bt_conn *conn, const struct bt_gatt_attr *attr, uint16_t mask); + +bool bt_gatt_attr_read_authorize(struct bt_conn *conn, const struct bt_gatt_attr *attr); +bool bt_gatt_attr_write_authorize(struct bt_conn *conn, const struct bt_gatt_attr *attr); diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 33306596b2ce..d2a8d6d1202b 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -1497,24 +1497,12 @@ void bt_hci_le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt) bt_addr_copy(&conn->le.resp_addr.a, &evt->local_rpa); } - /* if the controller supports, lets advertise for another - * peripheral connection. - * check for connectable advertising state is sufficient as - * this is how this le connection complete for peripheral occurred. - */ - if (BT_LE_STATES_PER_CONN_ADV(bt_dev.le.states)) { - bt_le_adv_resume(); - } - if (IS_ENABLED(CONFIG_BT_EXT_ADV) && !BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features)) { - struct bt_le_ext_adv *adv = bt_le_adv_lookup_legacy(); /* No advertising set terminated event, must be a * legacy advertiser set. */ - if (!atomic_test_bit(adv->flags, BT_ADV_PERSIST)) { - bt_le_adv_delete_legacy(); - } + bt_le_adv_delete_legacy(); } } @@ -3975,7 +3963,7 @@ const char *bt_hci_get_ver_str(uint8_t core_version) { const char * const str[] = { "1.0b", "1.1", "1.2", "2.0", "2.1", "3.0", "4.0", "4.1", "4.2", - "5.0", "5.1", "5.2", "5.3", "5.4", "6.0", "6.1" + "5.0", "5.1", "5.2", "5.3", "5.4", "6.0", "6.1", "6.2" }; if (core_version < ARRAY_SIZE(str)) { @@ -4662,6 +4650,10 @@ int bt_disable(void) bt_periodic_sync_disable(); #endif /* CONFIG_BT_PER_ADV_SYNC */ + if (IS_ENABLED(CONFIG_BT_ISO)) { + bt_iso_reset(); + } + #if defined(CONFIG_BT_CONN) if (IS_ENABLED(CONFIG_BT_SMP)) { bt_pub_key_hci_disrupted(); @@ -4716,10 +4708,6 @@ int bt_disable(void) /* If random address was set up - clear it */ bt_addr_le_copy(&bt_dev.random_addr, BT_ADDR_LE_ANY); - if (IS_ENABLED(CONFIG_BT_ISO)) { - bt_iso_reset(); - } - bt_monitor_send(BT_MONITOR_CLOSE_INDEX, NULL, 0); /* Clear BT_DEV_ENABLE here to prevent early bt_enable() calls, before disable is diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index 315db2d38884..e17277ba4da2 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -116,6 +116,10 @@ enum { BT_ADV_PARAMS_SET, /* Advertising data has been set in the controller. */ BT_ADV_DATA_SET, + /* Advertising random address has been updated in the controller before + * enabling advertising. + */ + BT_ADV_RANDOM_ADDR_UPDATED, /* Advertising random address pending to be set in the controller. */ BT_ADV_RANDOM_ADDR_PENDING, /* The private random address of the advertiser is valid for this cycle @@ -140,10 +144,6 @@ enum { * the identity address instead. */ BT_ADV_USE_IDENTITY, - /* Advertiser has been configured to keep advertising after a connection - * has been established as long as there are connections available. - */ - BT_ADV_PERSIST, /* Advertiser has been temporarily disabled. */ BT_ADV_PAUSED, /* Periodic Advertising has been enabled in the controller. */ @@ -497,7 +497,28 @@ struct bt_keys; void bt_id_add(struct bt_keys *keys); void bt_id_del(struct bt_keys *keys); -struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate); +/** @brief Find a conflict in the resolving list for a candidate IRK. + * + * @param candidate The candidate keys to check for conflicts. + * @param all If true, check all IRKs, otherwise check only added keys. + * + * @return The conflicting key if there is one, or NULL if no conflict was found. + */ +struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate, bool all); + +/** * @brief Find multiple conflicts in the resolving list for a candidate IRK. + * + * This function iterates over all keys (added and not added to the Resolving List). If there are + * multiple conflicts, this function will return true. Otherwise, it will return false. + * + * If @c firt_conflict is not NULL, it will be set to the first found conflict. + * + * @param candidate The candidate key to check for conflicts. + * @param first_conflict Pointer to store the first found conflict, if any. Can be NULL. + * + * @return True if there are multiple conflicts, otherwise it returns false. + */ +bool bt_id_find_conflict_multiple(struct bt_keys *candidate, struct bt_keys **first_conflict); int bt_setup_random_id_addr(void); int bt_setup_public_id_addr(void); diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c index a43aaef78f44..4c54460ab4df 100644 --- a/subsys/bluetooth/host/id.c +++ b/subsys/bluetooth/host/id.c @@ -803,12 +803,11 @@ bool bt_id_adv_random_addr_check(const struct bt_le_adv_param *param) * Explicitly stop it here. */ - if (!(param->options & _BT_LE_ADV_OPT_CONNECTABLE) && - (param->options & BT_LE_ADV_OPT_USE_IDENTITY)) { + if (!(param->options & BT_LE_ADV_OPT_CONN) && + (param->options & BT_LE_ADV_OPT_USE_IDENTITY)) { /* Attempt to set non-connectable NRPA */ return false; - } else if (bt_dev.id_addr[param->id].type == - BT_ADDR_LE_RANDOM && + } else if (bt_dev.id_addr[param->id].type == BT_ADDR_LE_RANDOM && param->id != BT_ID_DEFAULT) { /* Attempt to set connectable, or non-connectable with * identity different than scanner. @@ -942,9 +941,33 @@ void bt_id_pending_keys_update(void) } } +static bool keys_conflict_check(const struct bt_keys *candidate, const struct bt_keys *resident) +{ + bool addr_conflict; + bool irk_conflict; + + addr_conflict = bt_addr_le_eq(&candidate->addr, &resident->addr); + + /* All-zero IRK is "no IRK", and does not conflict with other Zero-IRKs. */ + irk_conflict = (!bt_irk_eq(&candidate->irk, &(struct bt_irk){}) && + bt_irk_eq(&candidate->irk, &resident->irk)); + + if (addr_conflict || irk_conflict) { + LOG_DBG("Resident : addr %s and IRK %s", bt_addr_le_str(&resident->addr), + bt_hex(resident->irk.val, sizeof(resident->irk.val))); + LOG_DBG("Candidate: addr %s and IRK %s", bt_addr_le_str(&candidate->addr), + bt_hex(candidate->irk.val, sizeof(candidate->irk.val))); + + return true; + } + + return false; +} + struct bt_id_conflict { struct bt_keys *candidate; struct bt_keys *found; + bool check_all_irk; }; /* The Controller Resolve List is constrained by 7.8.38 "LE Add Device To @@ -956,8 +979,6 @@ struct bt_id_conflict { static void find_rl_conflict(struct bt_keys *resident, void *user_data) { struct bt_id_conflict *conflict = user_data; - bool addr_conflict; - bool irk_conflict; __ASSERT_NO_MSG(conflict != NULL); __ASSERT_NO_MSG(conflict->candidate != NULL); @@ -970,32 +991,26 @@ static void find_rl_conflict(struct bt_keys *resident, void *user_data) } /* Test against committed bonds only. */ - if ((resident->state & BT_KEYS_ID_ADDED) == 0) { + if (!conflict->check_all_irk && (resident->state & BT_KEYS_ID_ADDED) == 0) { + /* If the resident bond is not committed, we cannot have a conflict. */ return; } - addr_conflict = bt_addr_le_eq(&conflict->candidate->addr, &resident->addr); - - /* All-zero IRK is "no IRK", and does not conflict with other Zero-IRKs. */ - irk_conflict = (!bt_irk_eq(&conflict->candidate->irk, &(struct bt_irk){}) && - bt_irk_eq(&conflict->candidate->irk, &resident->irk)); - - if (addr_conflict || irk_conflict) { - LOG_DBG("Resident : addr %s and IRK %s, id: %d", bt_addr_le_str(&resident->addr), - bt_hex(resident->irk.val, sizeof(resident->irk.val)), resident->id); - LOG_DBG("Candidate: addr %s and IRK %s, id: %d", - bt_addr_le_str(&conflict->candidate->addr), - bt_hex(conflict->candidate->irk.val, sizeof(conflict->candidate->irk.val)), - conflict->candidate->id); + if (resident->id == conflict->candidate->id) { + /* If the IDs are the same, we cannot have a conflict. */ + return; + } + if (keys_conflict_check(conflict->candidate, resident)) { conflict->found = resident; } } -struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate) +struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate, bool check_all_irk) { struct bt_id_conflict conflict = { .candidate = candidate, + .check_all_irk = check_all_irk, }; bt_keys_foreach_type(BT_KEYS_IRK, find_rl_conflict, &conflict); @@ -1003,6 +1018,59 @@ struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate) return conflict.found; } +struct bt_id_conflict_multiple { + struct bt_keys *candidate; + struct bt_keys *found; + bool found_multiple; +}; + +void find_rl_conflict_multiple(struct bt_keys *resident, void *user_data) +{ + struct bt_id_conflict_multiple *conflict = user_data; + + __ASSERT_NO_MSG(conflict != NULL); + __ASSERT_NO_MSG(conflict->candidate != NULL); + __ASSERT_NO_MSG(resident != NULL); + + if (conflict->found_multiple) { + /* If we already found enough conflicts, we can stop searching. */ + return; + } + + if (resident->id == conflict->candidate->id) { + /* If the IDs are the same, we cannot have a conflict. */ + return; + } + + if (keys_conflict_check(conflict->candidate, resident)) { + if (conflict->found) { + conflict->found_multiple = true; + + LOG_WRN("Found multiple conflicts for %s: addr %s and IRK %s", + bt_addr_le_str(&conflict->candidate->addr), + bt_addr_le_str(&resident->addr), + bt_hex(resident->irk.val, sizeof(resident->irk.val))); + } else { + conflict->found = resident; + } + } +} + +bool bt_id_find_conflict_multiple(struct bt_keys *candidate, struct bt_keys **first_conflict) +{ + struct bt_id_conflict_multiple conflict = { + .candidate = candidate, + }; + + bt_keys_foreach_type(BT_KEYS_IRK, find_rl_conflict_multiple, &conflict); + + if (first_conflict != NULL) { + *first_conflict = conflict.found; + } + + return conflict.found_multiple; +} + void bt_id_add(struct bt_keys *keys) { CHECKIF(keys == NULL) { @@ -1265,6 +1333,122 @@ void bt_id_del(struct bt_keys *keys) bt_le_ext_adv_foreach(adv_unpause_enabled, NULL); } } + +static int conflict_check_and_replace(uint8_t id, struct bt_keys *keys) +{ + /* For the given key check if it has conflicts with other keys in the Resolving List + * (such keys have BT_KEYS_ID_ADDED state and BT_KEYS_ID_CONFLICT flag set). If it does, we + * need to remove the conflicting key from the Resolving List and add the new key. + * + * If the key is not in the Resolving List, we can add the new key right away. + * + * If advertiser for the conflicting key is enabled, we cannot remove the key from the + * Resolving List, so we return an error. + */ + + struct bt_keys *conflict; + const struct bt_le_ext_adv *adv; + + if (!(keys->flags & BT_KEYS_ID_CONFLICT)) { + LOG_DBG("Key has no conflicts for id %u addr %s", id, bt_addr_le_str(&keys->addr)); + return 0; + } + + if (keys->state & BT_KEYS_ID_ADDED) { + LOG_DBG("Key is already added to resolving list for id %u addr %s", id, + bt_addr_le_str(&keys->addr)); + return 0; + } + + /* bt_id_find_conflict returns only keys added to the Resolving List (state is + * BT_KEYS_ID_ADDED). If the key has conflict, but no keys were added (for example, if the + * last added key was removed after bt_unpair()), then this function will return NULL. Then, + * we don't need to remove a conflicting key from the Resolving List. Otherwise, we need to + * remove the conflicting key from the Resolving List before adding the new key. + */ + conflict = bt_id_find_conflict(keys, false); + if (conflict != NULL) { + __ASSERT_NO_MSG((conflict->flags & BT_KEYS_ID_CONFLICT) != 0); + + LOG_DBG("Found conflicting key with id %u addr %s", conflict->id, + bt_addr_le_str(&conflict->addr)); + + adv = bt_adv_lookup_by_id(conflict->id); + if (adv && atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { + LOG_WRN("Cannot remove the conflicting key from the Resolving List while" + " advertising"); + return -EPERM; + } + + /* Drop BT_KEYS_ID_PENDING_DEL flag if we were about to delete the keys since we + * delete it here. + */ + conflict->state &= ~BT_KEYS_ID_PENDING_DEL; + bt_id_del(conflict); + } + + bt_id_add(keys); + + return 0; +} + +struct bt_id_resolve { + uint8_t id; + int err; +}; + +static void check_and_add_keys_for_id(struct bt_keys *keys, void *data) +{ + struct bt_id_resolve *resolve = data; + + if (resolve->err) { + /* Skipping other keys because we got error. */ + return; + } + + if (resolve->id != keys->id) { + /* We are only interested in keys for the given id */ + return; + } + + resolve->err = conflict_check_and_replace(resolve->id, keys); +} + +int bt_id_resolving_list_check_and_update(uint8_t id, const bt_addr_le_t *peer) +{ + int err; + + if (peer == NULL) { + struct bt_id_resolve resolve = { + .id = id, + }; + + LOG_DBG("Updating resolving list for id %u without peer address", id); + + bt_keys_foreach_type(BT_KEYS_IRK, check_and_add_keys_for_id, &resolve); + err = resolve.err; + } else { + struct bt_keys *keys; + + LOG_DBG("Updating resolving list for id %u addr %s", id, bt_addr_le_str(peer)); + + keys = bt_keys_get_addr(id, peer); + if (!keys) { + LOG_DBG("No keys found for id %u addr %s", id, bt_addr_le_str(peer)); + return -ENOENT; + } + + err = conflict_check_and_replace(id, keys); + } + + if (err) { + LOG_ERR("Failed to update resolving list for id %u addr %s (err %d)", id, + peer ? bt_addr_le_str(peer) : "NULL", err); + return err; + } + + return err; +} #endif /* defined(CONFIG_BT_SMP) */ void bt_id_get(bt_addr_le_t *addrs, size_t *count) @@ -1936,7 +2120,7 @@ int bt_id_set_adv_own_addr(struct bt_le_ext_adv *adv, uint32_t options, return 0; } - if (options & _BT_LE_ADV_OPT_CONNECTABLE) { + if (options & BT_LE_ADV_OPT_CONN) { if (dir_adv && (options & BT_LE_ADV_OPT_DIR_ADDR_RPA) && !BT_FEAT_LE_PRIVACY(bt_dev.le.features)) { return -ENOTSUP; diff --git a/subsys/bluetooth/host/id.h b/subsys/bluetooth/host/id.h index 8824d3bb496b..cd66784a5037 100644 --- a/subsys/bluetooth/host/id.h +++ b/subsys/bluetooth/host/id.h @@ -60,3 +60,26 @@ void bt_id_pending_keys_update(void); void bt_id_pending_keys_update_set(struct bt_keys *keys, uint8_t flag); void bt_id_adv_limited_stopped(struct bt_le_ext_adv *adv); + +/** + * @brief Check and update the resolving list for a given identity. + * + * This function checks if the resolving list contains the keys for the given + * identity and peer address. If the keys are not present, it adds them to the + * resolving list. If the keys are present, it checks for conflicts with + * existing keys in the resolving list. If a conflict is found, it replaces + * the conflicting key with the new key. + * + * If the peer address is NULL, it updates the resolving list for all keys that belong to the given + * identity. + * + * If for any of the keys belonging to the given identity a conflict is found and the advertiser for + * that key is enabled, the function returns an error. + * + * @param id The identity ID to check and update. + * @param peer The peer address to check against the resolving list. + * + * @return 0 on success, or a negative error code on failure. + * @return -EPERM if a conflict is found and the advertiser for the conflicting key is enabled. + */ +int bt_id_resolving_list_check_and_update(uint8_t id, const bt_addr_le_t *peer); diff --git a/subsys/bluetooth/host/keys.c b/subsys/bluetooth/host/keys.c index 1205494e856f..e2116f3bedeb 100644 --- a/subsys/bluetooth/host/keys.c +++ b/subsys/bluetooth/host/keys.c @@ -310,16 +310,57 @@ void bt_keys_add_type(struct bt_keys *keys, enum bt_keys_type type) keys->keys |= type; } +static void add_id_cb(struct k_work *work) +{ + bt_id_pending_keys_update(); +} + +static K_WORK_DEFINE(add_id_work, add_id_cb); + void bt_keys_clear(struct bt_keys *keys) { + struct bt_keys *conflict = NULL; + __ASSERT_NO_MSG(keys != NULL); LOG_DBG("%s (keys 0x%04x)", bt_addr_le_str(&keys->addr), keys->keys); + if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS) && + (keys->flags & BT_KEYS_ID_CONFLICT) != 0) { + /* We need to check how many conflicting keys left. If there is only one conflicting + * key left, we can remove the BT_KEYS_ID_CONFLICT flag from it so that Host don't + * need to check and update the Resolving List whenever this is needed. The key + * should be re-added to the Resolving List. + */ + bool found_multiple; + + found_multiple = bt_id_find_conflict_multiple(keys, &conflict); + if (conflict) { + if (found_multiple || (conflict->state & BT_KEYS_ID_ADDED) != 0) { + /* If we found multiple conflicting keys or the conflicting key + * is already added to the ID list, we don't need to clear the + * conflict flag for it and re-add it to the Resolving List. + */ + conflict = NULL; + } else { + /* Clear the conflict flag for the conflicting key */ + conflict->flags &= ~BT_KEYS_ID_CONFLICT; + } + } + } + if (keys->state & BT_KEYS_ID_ADDED) { bt_id_del(keys); } + if (conflict) { + /* Re-add the conflicting key to the Resolving List if it was the last conflicting + * key. + */ + bt_id_pending_keys_update_set(conflict, BT_KEYS_ID_PENDING_ADD); + k_work_submit(&add_id_work); + } + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { /* Delete stored keys from flash */ bt_settings_delete_keys(keys->id, &keys->addr); @@ -347,6 +388,28 @@ int bt_keys_store(struct bt_keys *keys) return 0; } +static void check_and_set_id_conflict_flag(struct bt_keys *keys) +{ + struct bt_keys *conflict; + + if (!IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + /* If auto-swap is not enabled, we don't need to check for conflicts */ + return; + } + + /* Use bt_id_find_conflict() to check if there are any conflicting keys for the given keys. + * If there is at least one, set the BT_KEYS_ID_CONFLICT flag for both the keys and the + * conflicting key. + */ + conflict = bt_id_find_conflict(keys, true); + if (conflict != NULL) { + LOG_DBG("Found conflicting key %p.", conflict); + + keys->flags |= BT_KEYS_ID_CONFLICT; + conflict->flags |= BT_KEYS_ID_CONFLICT; + } +} + static int keys_set(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { @@ -427,6 +490,8 @@ static int keys_set(const char *name, size_t len_rd, settings_read_cb read_cb, memcpy(keys->storage_start, val, len); } + check_and_set_id_conflict_flag(keys); + LOG_DBG("Successfully restored keys for %s", bt_addr_le_str(&addr)); #if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST) if (aging_counter_val < keys->aging_counter) { @@ -436,17 +501,17 @@ static int keys_set(const char *name, size_t len_rd, settings_read_cb read_cb, return 0; } -static void add_id_cb(struct k_work *work) -{ - bt_id_pending_keys_update(); -} - -static K_WORK_DEFINE(add_id_work, add_id_cb); - static void id_add(struct bt_keys *keys, void *user_data) { __ASSERT_NO_MSG(keys != NULL); + if (keys->flags & BT_KEYS_ID_CONFLICT) { + /* If the keys have the conflict flag set, we don't want to add them to the ID list, + * as this will cause issues with resolving list. + */ + return; + } + bt_id_pending_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD); k_work_submit(&add_id_work); } diff --git a/subsys/bluetooth/host/keys.h b/subsys/bluetooth/host/keys.h index b53635ce2c56..185fd610e779 100644 --- a/subsys/bluetooth/host/keys.h +++ b/subsys/bluetooth/host/keys.h @@ -45,6 +45,12 @@ enum { /* Bit 2 and 3 might accidentally exist in old stored keys */ BT_KEYS_SC = BIT(4), BT_KEYS_OOB = BIT(5), + /** Indicates that the keys are in conflict with existing keys. + * + * This is used to indicate that the keys being added conflict with + * existing keys from different identity. + */ + BT_KEYS_ID_CONFLICT = BIT(6), }; struct bt_ltk { diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index f65827fac1be..882ba9a037b4 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -50,6 +50,11 @@ LOG_MODULE_REGISTER(bt_l2cap, CONFIG_BT_L2CAP_LOG_LEVEL); #define L2CAP_LE_MAX_CREDITS (BT_BUF_ACL_RX_COUNT - 1) +#define L2CAP_LE_CID_FIXED_START 0x0001 +#define L2CAP_LE_CID_FIXED_END 0x003f +#define L2CAP_LE_CID_IS_FIXED(_cid) \ + (_cid >= L2CAP_LE_CID_FIXED_START && _cid <= L2CAP_LE_CID_FIXED_END) + #define L2CAP_LE_CID_DYN_START 0x0040 #define L2CAP_LE_CID_DYN_END 0x007f #define L2CAP_LE_CID_IS_DYN(_cid) \ @@ -273,6 +278,21 @@ static void l2cap_chan_del(struct bt_l2cap_chan *chan) * `l2cap_chan_destroy()` as it is not called for fixed channels. */ while ((buf = k_fifo_get(&le_chan->tx_queue, K_NO_WAIT))) { + bt_conn_tx_cb_t cb = closure_cb(buf->user_data); + + if (cb) { + void *user_data = closure_data(buf->user_data); + + /* When bt_l2cap_send_pdu() succeeds, the stack takes ownership + * and must invoke the callback eventually. Since these PDUs will + * never be transmitted, invoke the callback now with an error. + * Note: We cannot use conn_tx_destroy() here because no bt_conn_tx + * struct has been allocated yet - the closure is still in the + * buf->user_data. + */ + cb(chan->conn, user_data, -ESHUTDOWN); + } + net_buf_unref(buf); } @@ -410,6 +430,12 @@ void bt_l2cap_connected(struct bt_conn *conn) STRUCT_SECTION_FOREACH(bt_l2cap_fixed_chan, fchan) { struct bt_l2cap_le_chan *le_chan; + __ASSERT(L2CAP_LE_CID_IS_FIXED(fchan->cid), + "CID %u is not in the fixed channel range", fchan->cid); + + chan = bt_l2cap_le_lookup_tx_cid(conn, fchan->cid); + __ASSERT(chan == NULL, "Fixed channel with CID %u already exists", fchan->cid); + if (fchan->accept(conn, &chan) < 0) { continue; } @@ -422,7 +448,7 @@ void bt_l2cap_connected(struct bt_conn *conn) le_chan->rx.cid = fchan->cid; le_chan->tx.cid = fchan->cid; - if (!l2cap_chan_add(conn, chan, fchan->destroy)) { + if (!l2cap_chan_add(conn, chan, NULL)) { return; } @@ -761,13 +787,19 @@ int bt_l2cap_send_pdu(struct bt_l2cap_le_chan *le_chan, struct net_buf *pdu, return -ENOTCONN; } - if (pdu->ref != 1) { + /* If ATT sent callback is delayed until data transmission is done by BLE controller + * (CONFIG_BT_ATT_SENT_CB_AFTER_TX), the `chan_send` function from `att.c` introduces an + * additional reference. The reference is used to extend lifetime of the net buffer until + * the data transmission is confirmed by ACK of the remote (the reference is removed when + * the TX callback passed to `bt_l2cap_send_pdu` is called). + */ + if (pdu->ref > 1 + (cb ? 1 : 0)) { /* The host may alter the buf contents when fragmenting. Higher * layers cannot expect the buf contents to stay intact. Extra * refs suggests a silent data corruption would occur if not for * this error. */ - LOG_ERR("Expecting 1 ref, got %d", pdu->ref); + LOG_ERR("Expecting up to %d refs, got %d", cb ? 2 : 1, pdu->ref); return -EINVAL; } @@ -2936,7 +2968,10 @@ static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) return -ENOMEM; } -BT_L2CAP_CHANNEL_DEFINE(le_fixed_chan, BT_L2CAP_CID_LE_SIG, l2cap_accept, NULL); +BT_L2CAP_FIXED_CHANNEL_DEFINE(le_fixed_chan) = { + .cid = BT_L2CAP_CID_LE_SIG, + .accept = l2cap_accept, +}; void bt_l2cap_init(void) { @@ -3394,6 +3429,16 @@ static int bt_l2cap_dyn_chan_send(struct bt_l2cap_le_chan *le_chan, struct net_b return 0; } +#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */ + +static void l2cap_fixed_chan_sent_cb(struct bt_conn *conn, void *user_data, int err) +{ + struct bt_l2cap_chan *chan = user_data; + + if (chan->ops->sent) { + chan->ops->sent(chan); + } +} int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf) { @@ -3421,20 +3466,21 @@ int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf) return bt_l2cap_br_chan_send_cb(chan, buf, NULL, NULL); } - /* Sending over static channels is not supported by this fn. Use - * `bt_l2cap_send_pdu()` instead. - */ - if (IS_ENABLED(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)) { - struct bt_l2cap_le_chan *le_chan = BT_L2CAP_LE_CHAN(chan); + struct bt_l2cap_le_chan *le_chan = BT_L2CAP_LE_CHAN(chan); - __ASSERT_NO_MSG(le_chan); - __ASSERT_NO_MSG(L2CAP_LE_CID_IS_DYN(le_chan->tx.cid)); + __ASSERT_NO_MSG(le_chan); +#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL) + if (L2CAP_LE_CID_IS_DYN(le_chan->tx.cid)) { return bt_l2cap_dyn_chan_send(le_chan, buf); } +#endif + + if (L2CAP_LE_CID_IS_FIXED(le_chan->tx.cid)) { + return bt_l2cap_send_pdu(le_chan, buf, l2cap_fixed_chan_sent_cb, (void *)chan); + } LOG_DBG("Invalid channel type (chan %p)", chan); return -EINVAL; } -#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */ diff --git a/subsys/bluetooth/host/l2cap_internal.h b/subsys/bluetooth/host/l2cap_internal.h index 3f84b2b43d74..82d6d65434f9 100644 --- a/subsys/bluetooth/host/l2cap_internal.h +++ b/subsys/bluetooth/host/l2cap_internal.h @@ -26,12 +26,6 @@ enum l2cap_conn_list_action { BT_L2CAP_CHAN_DETACH, }; -#define BT_L2CAP_CID_BR_SIG 0x0001 -#define BT_L2CAP_CID_ATT 0x0004 -#define BT_L2CAP_CID_LE_SIG 0x0005 -#define BT_L2CAP_CID_SMP 0x0006 -#define BT_L2CAP_CID_BR_SMP 0x0007 - #define BT_L2CAP_PSM_RFCOMM 0x0003 struct bt_l2cap_hdr { @@ -164,19 +158,6 @@ struct bt_l2cap_ecred_reconf_rsp { uint16_t result; } __packed; -struct bt_l2cap_fixed_chan { - uint16_t cid; - int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan); - bt_l2cap_chan_destroy_t destroy; -}; - -#define BT_L2CAP_CHANNEL_DEFINE(_name, _cid, _accept, _destroy) \ - const STRUCT_SECTION_ITERABLE(bt_l2cap_fixed_chan, _name) = { \ - .cid = _cid, \ - .accept = _accept, \ - .destroy = _destroy, \ - } - /* Notify L2CAP channels of a new connection */ void bt_l2cap_connected(struct bt_conn *conn); diff --git a/subsys/bluetooth/host/scan.c b/subsys/bluetooth/host/scan.c index b154729438a0..8c5278f362c0 100644 --- a/subsys/bluetooth/host/scan.c +++ b/subsys/bluetooth/host/scan.c @@ -538,7 +538,6 @@ int bt_le_scan_user_remove(enum bt_le_scan_user flag) return scan_update(); } -#if defined(CONFIG_BT_CENTRAL) static void check_pending_conn(const bt_addr_le_t *id_addr, const bt_addr_le_t *addr, uint8_t adv_props) { @@ -593,7 +592,6 @@ static void check_pending_conn(const bt_addr_le_t *id_addr, LOG_WRN("Error while updating the scanner (%d)", err); } } -#endif /* CONFIG_BT_CENTRAL */ /* Convert Legacy adv report evt_type field to adv props */ static uint8_t get_adv_props_legacy(uint8_t evt_type) @@ -632,13 +630,14 @@ static void le_adv_recv(bt_addr_le_t *addr, struct bt_le_scan_recv_info *info, struct bt_le_scan_cb *listener, *next; struct net_buf_simple_state state; bt_addr_le_t id_addr; + bool explicit_scan = atomic_test_bit(scan_state.scan_flags, BT_LE_SCAN_USER_EXPLICIT_SCAN); + bool conn_scan = atomic_test_bit(scan_state.scan_flags, BT_LE_SCAN_USER_CONN); LOG_DBG("%s event %u, len %u, rssi %d dBm", bt_addr_le_str(addr), info->adv_type, len, info->rssi); if (!IS_ENABLED(CONFIG_BT_PRIVACY) && !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && - atomic_test_bit(scan_state.scan_flags, BT_LE_SCAN_USER_EXPLICIT_SCAN) && - (info->adv_props & BT_HCI_LE_ADV_PROP_DIRECT)) { + explicit_scan && (info->adv_props & BT_HCI_LE_ADV_PROP_DIRECT)) { LOG_DBG("Dropped direct adv report"); return; } @@ -652,6 +651,13 @@ static void le_adv_recv(bt_addr_le_t *addr, struct bt_le_scan_recv_info *info, bt_lookup_id_addr(BT_ID_DEFAULT, addr)); } + /* For connection-purpose scanning, + * skip app callbacks but allow pending-conn check logic. + */ + if (IS_ENABLED(CONFIG_BT_CENTRAL) && !explicit_scan && conn_scan) { + goto check_pending_conn; + } + if (scan_dev_found_cb) { net_buf_simple_save(buf, &state); @@ -677,9 +683,10 @@ static void le_adv_recv(bt_addr_le_t *addr, struct bt_le_scan_recv_info *info, /* Clear pointer to this stack frame before returning to calling function */ info->addr = NULL; -#if defined(CONFIG_BT_CENTRAL) - check_pending_conn(&id_addr, addr, info->adv_props); -#endif /* CONFIG_BT_CENTRAL */ +check_pending_conn: + if (IS_ENABLED(CONFIG_BT_CENTRAL)) { + check_pending_conn(&id_addr, addr, info->adv_props); + } } #if defined(CONFIG_BT_EXT_ADV) @@ -805,6 +812,8 @@ static void create_ext_adv_info(struct bt_hci_evt_le_ext_advertising_info const void bt_hci_le_adv_ext_report(struct net_buf *buf) { uint8_t num_reports = net_buf_pull_u8(buf); + bool explicit_scan = atomic_test_bit(scan_state.scan_flags, BT_LE_SCAN_USER_EXPLICIT_SCAN); + bool conn_scan = atomic_test_bit(scan_state.scan_flags, BT_LE_SCAN_USER_CONN); LOG_DBG("Adv number of reports %u", num_reports); @@ -817,19 +826,23 @@ void bt_hci_le_adv_ext_report(struct net_buf *buf) bool more_to_come; bool is_new_advertiser; - if (!atomic_test_bit(scan_state.scan_flags, BT_LE_SCAN_USER_EXPLICIT_SCAN)) { + if (!explicit_scan) { /* The application has not requested explicit scan, so it is not expecting * advertising reports. Discard, and reset the reassembler if not inactive * This is done in the loop as this flag can change between each iteration, * and it is not uncommon that scanning is disabled in the callback called - * from le_adv_recv + * from le_adv_recv. + * + * However, if scanning is running for connection purposes, + * the report shall still be processed to allow pending connections. */ - if (reassembling_advertiser.state != FRAG_ADV_INACTIVE) { reset_reassembling_advertiser(); } - break; + if (!conn_scan) { + break; + } } if (buf->len < sizeof(*evt)) { @@ -1669,18 +1682,23 @@ void bt_hci_le_adv_report(struct net_buf *buf) { uint8_t num_reports = net_buf_pull_u8(buf); struct bt_hci_evt_le_advertising_info *evt; + bool explicit_scan = atomic_test_bit(scan_state.scan_flags, BT_LE_SCAN_USER_EXPLICIT_SCAN); + bool conn_scan = atomic_test_bit(scan_state.scan_flags, BT_LE_SCAN_USER_CONN); LOG_DBG("Adv number of reports %u", num_reports); while (num_reports--) { struct bt_le_scan_recv_info adv_info; - if (!atomic_test_bit(scan_state.scan_flags, BT_LE_SCAN_USER_EXPLICIT_SCAN)) { + if (!explicit_scan && !conn_scan) { /* The application has not requested explicit scan, so it is not expecting * advertising reports. Discard. * This is done in the loop as this flag can change between each iteration, * and it is not uncommon that scanning is disabled in the callback called - * from le_adv_recv + * from le_adv_recv. + * + * However, if scanning is running for connection purposes, + * the report shall still be processed to allow pending connections. */ break; @@ -1841,11 +1859,10 @@ void bt_le_scan_cb_unregister(struct bt_le_scan_cb *cb) #if defined(CONFIG_BT_PER_ADV_SYNC) uint8_t bt_le_per_adv_sync_get_index(struct bt_le_per_adv_sync *per_adv_sync) { - ptrdiff_t index = per_adv_sync - per_adv_sync_pool; - - __ASSERT(index >= 0 && ARRAY_SIZE(per_adv_sync_pool) > index, + __ASSERT(IS_ARRAY_ELEMENT(per_adv_sync_pool, per_adv_sync), "Invalid per_adv_sync pointer"); - return (uint8_t)index; + + return (uint8_t)ARRAY_INDEX(per_adv_sync_pool, per_adv_sync); } struct bt_le_per_adv_sync *bt_le_per_adv_sync_lookup_index(uint8_t index) diff --git a/subsys/bluetooth/host/shell/bt.c b/subsys/bluetooth/host/shell/bt.c index a09afe4e3e5c..816b6549853b 100644 --- a/subsys/bluetooth/host/shell/bt.c +++ b/subsys/bluetooth/host/shell/bt.c @@ -4421,6 +4421,15 @@ static void br_bond_deleted(const bt_addr_t *peer) } #endif /* CONFIG_BT_CLASSIC */ +#if defined(CONFIG_BT_APP_PASSKEY) +static uint32_t app_passkey = BT_PASSKEY_RAND; + +static uint32_t auth_app_passkey(struct bt_conn *conn) +{ + return app_passkey; +} +#endif /* CONFIG_BT_APP_PASSKEY */ + static struct bt_conn_auth_cb auth_cb_display = { .passkey_display = auth_passkey_display, #if defined(CONFIG_BT_PASSKEY_KEYPRESS) @@ -4437,6 +4446,9 @@ static struct bt_conn_auth_cb auth_cb_display = { #if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT) .pairing_accept = pairing_accept, #endif +#if defined(CONFIG_BT_APP_PASSKEY) + .app_passkey = auth_app_passkey, +#endif }; static struct bt_conn_auth_cb auth_cb_display_yes_no = { @@ -4445,6 +4457,9 @@ static struct bt_conn_auth_cb auth_cb_display_yes_no = { .passkey_confirm = auth_passkey_confirm, #if defined(CONFIG_BT_CLASSIC) .pincode_entry = auth_pincode_entry, +#endif +#if defined(CONFIG_BT_APP_PASSKEY) + .app_passkey = auth_app_passkey, #endif .oob_data_request = NULL, .cancel = auth_cancel, @@ -4460,6 +4475,9 @@ static struct bt_conn_auth_cb auth_cb_input = { .passkey_confirm = NULL, #if defined(CONFIG_BT_CLASSIC) .pincode_entry = auth_pincode_entry, +#endif +#if defined(CONFIG_BT_APP_PASSKEY) + .app_passkey = auth_app_passkey, #endif .oob_data_request = NULL, .cancel = auth_cancel, @@ -4472,6 +4490,9 @@ static struct bt_conn_auth_cb auth_cb_input = { static struct bt_conn_auth_cb auth_cb_confirm = { #if defined(CONFIG_BT_CLASSIC) .pincode_entry = auth_pincode_entry, +#endif +#if defined(CONFIG_BT_APP_PASSKEY) + .app_passkey = auth_app_passkey, #endif .oob_data_request = NULL, .cancel = auth_cancel, @@ -4487,6 +4508,9 @@ static struct bt_conn_auth_cb auth_cb_all = { .passkey_confirm = auth_passkey_confirm, #if defined(CONFIG_BT_CLASSIC) .pincode_entry = auth_pincode_entry, +#endif +#if defined(CONFIG_BT_APP_PASSKEY) + .app_passkey = auth_app_passkey, #endif .oob_data_request = auth_pairing_oob_data_request, .cancel = auth_cancel, @@ -4703,16 +4727,15 @@ static int cmd_fal_connect(const struct shell *sh, size_t argc, char *argv[]) #endif /* CONFIG_BT_CENTRAL */ #endif /* defined(CONFIG_BT_FILTER_ACCEPT_LIST) */ -#if defined(CONFIG_BT_FIXED_PASSKEY) -static int cmd_fixed_passkey(const struct shell *sh, - size_t argc, char *argv[]) +#if defined(CONFIG_BT_APP_PASSKEY) +static int cmd_app_passkey(const struct shell *sh, + size_t argc, char *argv[]) { - unsigned int passkey; - int err; + uint32_t passkey; if (argc < 2) { - bt_passkey_set(BT_PASSKEY_INVALID); - shell_print(sh, "Fixed passkey cleared"); + app_passkey = BT_PASSKEY_RAND; + shell_print(sh, "App passkey cleared"); return 0; } @@ -4722,14 +4745,12 @@ static int cmd_fixed_passkey(const struct shell *sh, return -ENOEXEC; } - err = bt_passkey_set(passkey); - if (err) { - shell_print(sh, "Setting fixed passkey failed (err %d)", err); - } + app_passkey = passkey; + shell_print(sh, "App passkey set to %06u", passkey); - return err; + return 0; } -#endif +#endif /* CONFIG_BT_APP_PASSKEY */ static int cmd_auth_passkey(const struct shell *sh, size_t argc, char *argv[]) @@ -5340,10 +5361,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds, cmd_fal_connect, 2, 3), #endif /* CONFIG_BT_CENTRAL */ #endif /* defined(CONFIG_BT_FILTER_ACCEPT_LIST) */ -#if defined(CONFIG_BT_FIXED_PASSKEY) - SHELL_CMD_ARG(fixed-passkey, NULL, "[passkey]", cmd_fixed_passkey, +#if defined(CONFIG_BT_APP_PASSKEY) + SHELL_CMD_ARG(app-passkey, NULL, "[passkey]", cmd_app_passkey, 1, 1), -#endif +#endif /* CONFIG_BT_APP_PASSKEY */ #endif /* CONFIG_BT_SMP || CONFIG_BT_CLASSIC) */ #endif /* CONFIG_BT_CONN */ diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 4590f5d411a1..1e28a4e0c84f 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -222,10 +222,10 @@ struct bt_smp { atomic_t bondable; }; -static unsigned int fixed_passkey = BT_PASSKEY_INVALID; +static unsigned int fixed_passkey = BT_PASSKEY_RAND; #define DISPLAY_FIXED(smp) (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && \ - fixed_passkey != BT_PASSKEY_INVALID && \ + fixed_passkey != BT_PASSKEY_RAND && \ (smp)->method == PASSKEY_DISPLAY) #if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) @@ -363,9 +363,21 @@ static uint8_t get_io_capa(struct bt_smp *smp) return BT_SMP_IO_DISPLAY_YESNO; } +#if defined(CONFIG_BT_APP_PASSKEY) + /* Implementation of the app_passkey cb implies that the application can "know" the passkey + * without actually having a display, thus earning the "display" capability. + */ + if (smp_auth_cb->app_passkey) { + if (smp_auth_cb->passkey_entry) { + return BT_SMP_IO_KEYBOARD_DISPLAY; + } + + return BT_SMP_IO_DISPLAY_ONLY; + } +#endif /* CONFIG_BT_APP_PASSKEY */ + if (smp_auth_cb->passkey_entry) { - if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && - fixed_passkey != BT_PASSKEY_INVALID) { + if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && fixed_passkey != BT_PASSKEY_RAND) { return BT_SMP_IO_KEYBOARD_DISPLAY; } else { return BT_SMP_IO_KEYBOARD_ONLY; @@ -377,8 +389,7 @@ static uint8_t get_io_capa(struct bt_smp *smp) } no_callbacks: - if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && - fixed_passkey != BT_PASSKEY_INVALID) { + if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && fixed_passkey != BT_PASSKEY_RAND) { return BT_SMP_IO_DISPLAY_ONLY; } else { return BT_SMP_IO_NO_INPUT_OUTPUT; @@ -910,7 +921,7 @@ static void smp_br_id_add_replace(struct bt_keys *keys) bt_id_del(keys); } - conflict = bt_id_find_conflict(keys); + conflict = bt_id_find_conflict(keys, false); if (conflict != NULL) { int err; @@ -920,7 +931,7 @@ static void smp_br_id_add_replace(struct bt_keys *keys) __ASSERT_NO_MSG(!err); } - __ASSERT_NO_MSG(!bt_id_find_conflict(keys)); + __ASSERT_NO_MSG(!bt_id_find_conflict(keys, false)); bt_id_add(keys); } @@ -2020,7 +2031,15 @@ static void smp_timeout(struct k_work *work) struct k_work_delayable *dwork = k_work_delayable_from_work(work); struct bt_smp *smp = CONTAINER_OF(dwork, struct bt_smp, work); - LOG_ERR("SMP Timeout"); + /* if number of flags or supported commands exceed capacity of one + * atomic variable following error log shall be extended + */ + BUILD_ASSERT(ATOMIC_BITMAP_SIZE(SMP_NUM_FLAGS) == 1); + BUILD_ASSERT(ATOMIC_BITMAP_SIZE(BT_SMP_NUM_CMDS) == 1); + + LOG_ERR("SMP Timeout (flags:0x%08x allowed_cmds:0x%08x)", + (unsigned int)atomic_get(&smp->flags[0]), + (unsigned int)atomic_get(&smp->allowed_cmds[0])); smp_pairing_complete(smp, BT_SMP_ERR_UNSPECIFIED); @@ -2467,7 +2486,6 @@ static uint8_t legacy_request_tk(struct bt_smp *smp) struct bt_conn *conn = smp->chan.chan.conn; const struct bt_conn_auth_cb *smp_auth_cb = latch_auth_cb(smp); struct bt_keys *keys; - uint32_t passkey; /* * Fail if we have keys that are stronger than keys that will be @@ -2495,11 +2513,25 @@ static uint8_t legacy_request_tk(struct bt_smp *smp) } break; - case PASSKEY_DISPLAY: - if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && - fixed_passkey != BT_PASSKEY_INVALID) { + case PASSKEY_DISPLAY: { + uint32_t passkey; + + if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && fixed_passkey != BT_PASSKEY_RAND) { passkey = fixed_passkey; - } else { +#if defined(CONFIG_BT_APP_PASSKEY) + } else if (smp_auth_cb && smp_auth_cb->app_passkey) { + passkey = smp_auth_cb->app_passkey(conn); + + if (passkey != BT_PASSKEY_RAND && passkey > 999999) { + LOG_WRN("App-provided passkey is out of valid range: %u", passkey); + return BT_SMP_ERR_UNSPECIFIED; + } +#endif /* CONFIG_BT_APP_PASSKEY */ + } else { + passkey = BT_PASSKEY_RAND; + } + + if (passkey == BT_PASSKEY_RAND) { if (bt_rand(&passkey, sizeof(passkey))) { return BT_SMP_ERR_UNSPECIFIED; } @@ -2519,6 +2551,7 @@ static uint8_t legacy_request_tk(struct bt_smp *smp) sys_put_le32(passkey, smp->tk); break; + } case PASSKEY_INPUT: atomic_set_bit(smp->flags, SMP_FLAG_USER); smp_auth_cb->passkey_entry(conn); @@ -4096,16 +4129,24 @@ static uint8_t smp_id_add_replace(struct bt_smp *smp, struct bt_keys *new_bond) */ __ASSERT_NO_MSG(!(smp->remote_dist & BT_SMP_DIST_ID_KEY)); - conflict = bt_id_find_conflict(new_bond); + conflict = bt_id_find_conflict(new_bond, IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)); if (conflict) { LOG_DBG("New bond conflicts with a bond on id %d.", conflict->id); } - if (conflict && !IS_ENABLED(CONFIG_BT_ID_UNPAIR_MATCHING_BONDS)) { + if (conflict && !IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS) && + !IS_ENABLED(CONFIG_BT_ID_UNPAIR_MATCHING_BONDS)) { LOG_WRN("Refusing new pairing. The old bond must be unpaired first."); return BT_SMP_ERR_AUTH_REQUIREMENTS; } + if (conflict && IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + LOG_WRN("Conflict detected with %p. Don't add key to Resolve List.", conflict); + new_bond->flags |= BT_KEYS_ID_CONFLICT; + conflict->flags |= BT_KEYS_ID_CONFLICT; + return 0; + } + if (conflict && IS_ENABLED(CONFIG_BT_ID_UNPAIR_MATCHING_BONDS)) { bool trust_ok; int unpair_err; @@ -4122,7 +4163,7 @@ static uint8_t smp_id_add_replace(struct bt_smp *smp, struct bt_keys *new_bond) __ASSERT_NO_MSG(!unpair_err); } - __ASSERT_NO_MSG(!bt_id_find_conflict(new_bond)); + __ASSERT_NO_MSG(!bt_id_find_conflict(new_bond, false)); bt_id_add(new_bond); return 0; } @@ -4421,18 +4462,32 @@ __maybe_unused static uint8_t display_passkey(struct bt_smp *smp) { struct bt_conn *conn = smp->chan.chan.conn; const struct bt_conn_auth_cb *smp_auth_cb = latch_auth_cb(smp); + uint32_t passkey = BT_PASSKEY_RAND; - if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && - fixed_passkey != BT_PASSKEY_INVALID) { - smp->passkey = fixed_passkey; - } else { - if (bt_rand(&smp->passkey, sizeof(smp->passkey))) { + if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && fixed_passkey != BT_PASSKEY_RAND) { + passkey = fixed_passkey; + } + +#if defined(CONFIG_BT_APP_PASSKEY) + if (smp_auth_cb && smp_auth_cb->app_passkey) { + passkey = smp_auth_cb->app_passkey(conn); + + if (passkey != BT_PASSKEY_RAND && passkey > 999999) { + LOG_WRN("App-provided passkey is out of valid range: %u", passkey); + return BT_SMP_ERR_UNSPECIFIED; + } + } +#endif /* CONFIG_BT_APP_PASSKEY */ + + if (passkey == BT_PASSKEY_RAND) { + if (bt_rand(&passkey, sizeof(passkey))) { return BT_SMP_ERR_UNSPECIFIED; } - smp->passkey %= 1000000; + passkey %= 1000000; } + smp->passkey = passkey; smp->passkey_round = 0U; if (smp_auth_cb && smp_auth_cb->passkey_display) { @@ -6164,8 +6219,8 @@ int bt_smp_auth_pairing_confirm(struct bt_conn *conn) #if defined(CONFIG_BT_FIXED_PASSKEY) int bt_passkey_set(unsigned int passkey) { - if (passkey == BT_PASSKEY_INVALID) { - fixed_passkey = BT_PASSKEY_INVALID; + if (passkey == BT_PASSKEY_INVALID || passkey == BT_PASSKEY_RAND) { + fixed_passkey = BT_PASSKEY_RAND; return 0; } @@ -6346,7 +6401,10 @@ static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) return -ENOMEM; } -BT_L2CAP_CHANNEL_DEFINE(smp_fixed_chan, BT_L2CAP_CID_SMP, bt_smp_accept, NULL); +BT_L2CAP_FIXED_CHANNEL_DEFINE(smp_fixed_chan) = { + .cid = BT_L2CAP_CID_SMP, + .accept = bt_smp_accept, +}; #if defined(CONFIG_BT_CLASSIC) BT_L2CAP_BR_CHANNEL_DEFINE(smp_br_fixed_chan, BT_L2CAP_CID_BR_SMP, bt_smp_br_accept); diff --git a/subsys/bluetooth/host/smp_null.c b/subsys/bluetooth/host/smp_null.c index 0ff20b4a16d6..92a6596860e0 100644 --- a/subsys/bluetooth/host/smp_null.c +++ b/subsys/bluetooth/host/smp_null.c @@ -102,7 +102,10 @@ static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) return -ENOMEM; } -BT_L2CAP_CHANNEL_DEFINE(smp_fixed_chan, BT_L2CAP_CID_SMP, bt_smp_accept, NULL); +BT_L2CAP_FIXED_CHANNEL_DEFINE(smp_fixed_chan) = { + .cid = BT_L2CAP_CID_SMP, + .accept = bt_smp_accept, +}; int bt_smp_init(void) { diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 2c03c4e9ea3f..069dbe218f5e 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -59,12 +59,16 @@ choice BT_MESH_ADV menuconfig BT_MESH_ADV_LEGACY bool "Legacy advertising" + depends on BT_LL_SW_SPLIT help Use legacy advertising commands for mesh sending. Legacy - advertising is significantly slower than the extended advertising, but - is supported by all controllers. + advertising is significantly slower than the extended advertising. - WARNING: The legacy advertiser can occasionally do more message + WARNING: This feature is not supported in NCS. The legacy advertiser will not work + with SDC, as attempting to start an advertisement during the scanner duty cycle + will result in an error. The Zephyr Link Layer can be used experimentally as an + alternative. + The legacy advertiser can occasionally do more message retransmissions than requested because of limitations of HCI interface API. @@ -72,7 +76,8 @@ if BT_MESH_ADV_LEGACY config BT_MESH_ADV_STACK_SIZE int "Mesh advertiser thread stack size" - default 1024 if BT_HOST_CRYPTO + default 1800 if BT_MESH_PROVISIONER + default 1536 if BT_MESH_PROXY default 776 if BT_MESH_PRIV_BEACONS default 768 help @@ -142,8 +147,8 @@ if BT_MESH_WORKQ_MESH config BT_MESH_ADV_STACK_SIZE int "Mesh extended advertiser thread stack size" + default 2048 if BT_MESH_PROVISIONER default 1536 if BT_MESH_PROXY - default 1024 if BT_HOST_CRYPTO default 776 if BT_MESH_PRIV_BEACONS default 768 help @@ -210,6 +215,17 @@ config BT_MESH_ADV_EXT_FRIEND_SEPARATE messages as close to the start of the ReceiveWindow as possible, thus reducing the scanning time on the Low Power node. +config BT_MESH_ADV_EXT_ACCEPT_EXT_ADV_PACKETS + bool "Reject or accept extended advertising packets" + depends on BT_LL_SOFTDEVICE + help + Configure the scanner and initiator to either reject or accept extended + advertising packets by the SoftDevice Controller. This is set to false + by default, to prevent loss of scan time when receiving a pointer packet + while scanning for Bluetooth Mesh packets. Set to true if extended + advertising packets are to be received by the SoftDevice Controller for + purposes other than Bluetooth Mesh. + endif # BT_MESH_ADV_EXT endchoice @@ -360,6 +376,18 @@ config BT_MESH_OOB_AUTH_REQUIRED bool "OOB authentication mandates to use HMAC SHA256" depends on BT_MESH_ECDH_P256_HMAC_SHA256_AES_CCM +config BT_MESH_PROV_OOB_API_LEGACY + bool "Reduced maximum OOB authentication size support [DEPRECATED]" + select DEPRECATED + depends on BT_MESH_PROV + help + By default, the maximum OOB authentication size is 32 bytes. + Enable this option to use the legacy API which is only compatible with + specification v1.1 and earlier. This limits OOB authentication to 8 + bytes maximum. + This option is intended for backward compatibility. + Not recommended for new designs due to reduced security. + config BT_MESH_PROVISIONER bool "Provisioner support" depends on BT_MESH_CDB @@ -1038,6 +1066,7 @@ config BT_MESH_BLOB_IO_FLASH default y depends on BT_MESH_BLOB_SRV || BT_MESH_BLOB_CLI depends on FLASH_MAP + depends on FLASH_PAGE_LAYOUT help Enable the BLOB flash stream for reading and writing BLOBs directly to and from flash. @@ -1045,24 +1074,28 @@ config BT_MESH_BLOB_IO_FLASH if BT_MESH_BLOB_IO_FLASH config BT_MESH_BLOB_IO_FLASH_WITHOUT_ERASE - bool "BLOB flash support for devices without erase" - default y if FLASH_HAS_NO_EXPLICIT_ERASE + bool "BLOB flash support for devices without erase [DEPRECATED]" + default n depends on FLASH_HAS_NO_EXPLICIT_ERASE + select DEPRECATED help - Enable path supporting devices without erase. This option appears only - if there are devices without explicit erase requirements in the system - and may be disabled to reduce code size in case when no operations - are intended on such type of devices. + This option is deprecated and is no longer used by the BLOB IO Flash module. config BT_MESH_BLOB_IO_FLASH_WITH_ERASE - bool "BLOB flash support for devices with erase" - default y if FLASH_HAS_EXPLICIT_ERASE + bool "BLOB flash support for devices with erase [DEPRECATED]" + default n depends on FLASH_HAS_EXPLICIT_ERASE + depends on FLASH_PAGE_LAYOUT + select DEPRECATED help - Enable path supporting devices with erase. This option appears only - if there are devices requiring erase, before write, in the system - and may be disabled to reduce code size in case when no operations - are intended on such type of devices. + This option is deprecated and is no longer used by the BLOB IO Flash module. + +config BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX + int "Maximum supported write block size" + default 4 + help + The BLOB IO Flash module will support flash devices with explicit erase + when this value is set to a multiple of the device write block size. endif # BT_MESH_BLOB_IO_FLASH @@ -1692,7 +1725,7 @@ config BT_MESH_LPN_INIT_POLL_TIMEOUT config BT_MESH_LPN_SCAN_LATENCY int "Latency for enabling scanning" range 0 50 - default 15 + default 2 help Latency in milliseconds that it takes to enable scanning. This is in practice how much time in advance before the Receive Window diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index b056f74a5876..0cfaec39fdb7 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -13,6 +13,9 @@ #include #include #include +#if defined(CONFIG_BT_LL_SOFTDEVICE) +#include +#endif #include "common/bt_str.h" @@ -149,6 +152,28 @@ static inline struct bt_mesh_ext_adv *gatt_adv_get(void) } } +static int set_adv_randomness(uint8_t handle, int rand_us) +{ +#if defined(CONFIG_BT_LL_SOFTDEVICE) + struct net_buf *buf; + sdc_hci_cmd_vs_set_adv_randomness_t *cmd_params; + + buf = bt_hci_cmd_alloc(K_FOREVER); + if (!buf) { + LOG_ERR("Could not allocate command buffer"); + return -ENOMEM; + } + + cmd_params = net_buf_add(buf, sizeof(*cmd_params)); + cmd_params->adv_handle = handle; + cmd_params->rand_us = rand_us; + + return bt_hci_cmd_send_sync(SDC_HCI_OPCODE_CMD_VS_SET_ADV_RANDOMNESS, buf, NULL); +#else + return 0; +#endif /* defined(CONFIG_BT_LL_SOFTDEVICE) */ +} + static int adv_start(struct bt_mesh_ext_adv *ext_adv, const struct bt_le_adv_param *param, struct bt_le_ext_adv_start_param *start, @@ -391,6 +416,16 @@ static bool schedule_send(struct bt_mesh_ext_adv *ext_adv) if (!atomic_test_bit(ext_adv->flags, ADV_FLAG_PROXY)) { return false; } + } else if (k_work_is_pending(&ext_adv->work) && + !atomic_test_bit(ext_adv->flags, ADV_FLAG_PROXY)) { + /* This can happen if we try to schedule a send while a previous send is still + * pending in the work queue. There is nothing wrong with resubmitting the same + * work to the work queue, but in this case won't have a change to try a work from + * another advertising set which can be ready for sending. + * + * If, however, ADV_FLAG_PROXY is set, we want to stop the proxy advertising. + */ + return false; } bt_mesh_wq_submit(&ext_adv->work); @@ -494,6 +529,18 @@ void bt_mesh_adv_init(void) K_PRIO_COOP(MESH_WORKQ_PRIORITY), NULL); k_thread_name_set(&bt_mesh_workq.thread, "BT MESH WQ"); } + +#if defined(CONFIG_BT_LL_SOFTDEVICE) + const sdc_hci_cmd_vs_scan_accept_ext_adv_packets_set_t cmd_params = { + .accept_ext_adv_packets = IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_ACCEPT_EXT_ADV_PACKETS), + }; + + int err = sdc_hci_cmd_vs_scan_accept_ext_adv_packets_set(&cmd_params); + + if (err) { + LOG_ERR("Failed to set accept_ext_adv_packets: %d", err); + } +#endif } static struct bt_mesh_ext_adv *adv_instance_find(struct bt_le_ext_adv *instance) @@ -542,6 +589,15 @@ int bt_mesh_adv_enable(void) if (err) { return err; } + + if (IS_ENABLED(CONFIG_BT_LL_SOFTDEVICE) && + IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && + advs[i].tags == BT_MESH_ADV_TAG_BIT_FRIEND) { + err = set_adv_randomness(advs[i].instance->handle, 0); + if (err) { + LOG_ERR("Failed to set zero randomness: %d", err); + } + } } return 0; diff --git a/subsys/bluetooth/mesh/app_keys.c b/subsys/bluetooth/mesh/app_keys.c index 5afd887a8e80..f573add5a324 100644 --- a/subsys/bluetooth/mesh/app_keys.c +++ b/subsys/bluetooth/mesh/app_keys.c @@ -666,6 +666,10 @@ static int app_key_set(const char *name, size_t len_rd, uint16_t app_idx; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/bluetooth/mesh/blob_io_flash.c b/subsys/bluetooth/mesh/blob_io_flash.c index 8d989a6feca5..792c53d4a0a6 100644 --- a/subsys/bluetooth/mesh/blob_io_flash.c +++ b/subsys/bluetooth/mesh/blob_io_flash.c @@ -12,13 +12,17 @@ #include "net.h" #include "transport.h" -#define WRITE_BLOCK_SIZE DT_PROP(DT_INST(0, soc_nv_flash), write_block_size) +#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL +#include +LOG_MODULE_REGISTER(bt_mesh_blob_io_flash); #define FLASH_IO(_io) CONTAINER_OF(_io, struct bt_mesh_blob_io_flash, io) static int test_flash_area(uint8_t area_id) { + const struct flash_parameters *fparam; const struct flash_area *area; + const struct device *fdev; uint8_t align; int err; @@ -28,9 +32,19 @@ static int test_flash_area(uint8_t area_id) } align = flash_area_align(area); + fdev = flash_area_get_device(area); + fparam = flash_get_parameters(fdev); + flash_area_close(area); - if (align > WRITE_BLOCK_SIZE) { + if (!fdev) { + return -ENODEV; + } + + if ((flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT) && + CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX % align) { + LOG_ERR("CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX must be set to a\n" + "multiple of the write block size for the flash deviced used."); return -EINVAL; } @@ -58,40 +72,35 @@ static void io_close(const struct bt_mesh_blob_io *io, static inline int erase_device_block(const struct flash_area *fa, off_t start, size_t size) { - /* If there are no devices requiring erase, then there is nothing to do */ - if (IS_ENABLED(CONFIG_BT_MESH_BLOB_IO_FLASH_WITH_ERASE)) { - const struct device *fdev = flash_area_get_device(fa); - - if (!fdev) { - return -ENODEV; - } - - /* We have a mix of devices in system */ - if (IS_ENABLED(CONFIG_BT_MESH_BLOB_IO_FLASH_WITHOUT_ERASE)) { - const struct flash_parameters *fparam = flash_get_parameters(fdev); - - /* If device has no erase requirement then do nothing */ - if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) { - return 0; - } - } - - if (IS_ENABLED(CONFIG_FLASH_PAGE_LAYOUT)) { - struct flash_pages_info page; - int err; - - err = flash_get_page_info_by_offs(fdev, start, &page); - if (err) { - return err; - } - - size = page.size * DIV_ROUND_UP(size, page.size); - start = page.start_offset; - } - return flash_area_erase(fa, start, size); + const struct device *fdev = flash_area_get_device(fa); + struct flash_pages_info page; + int err; + + if (!fdev) { + return -ENODEV; } - return 0; + const struct flash_parameters *fparam = flash_get_parameters(fdev); + + /* If device has no erase requirement then do nothing */ + if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) { + return 0; + } + + err = flash_get_page_info_by_offs(fdev, start, &page); + if (err) { + return err; + } + + if (start != page.start_offset) { + /* Only need to erase when starting the first block on the page. */ + return 0; + } + + /* Align to page boundary. */ + size = page.size * DIV_ROUND_UP(size, page.size); + + return flash_area_erase(fa, start, size); } static int block_start(const struct bt_mesh_blob_io *io, @@ -125,30 +134,49 @@ static int wr_chunk(const struct bt_mesh_blob_io *io, const struct bt_mesh_blob_chunk *chunk) { struct bt_mesh_blob_io_flash *flash = FLASH_IO(io); + const struct device *fdev = flash_area_get_device(flash->area); + + if (!fdev) { + return -ENODEV; + } - if (IS_ENABLED(CONFIG_SOC_FLASH_NRF_RRAM)) { + const struct flash_parameters *fparam = flash_get_parameters(fdev); + + /* + * If device has no erase requirement then write directly. + * This is required since trick with padding using the erase value will + * not work in this case. + */ + if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) { return flash_area_write(flash->area, flash->offset + block->offset + chunk->offset, chunk->data, chunk->size); } - uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, WRITE_BLOCK_SIZE)]; + /* + * Allocate one additional write block for the case where a chunk will need + * an extra write block on both sides to fit. + */ + uint8_t buf[ROUND_UP(BLOB_RX_CHUNK_SIZE, CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX) + + CONFIG_BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX]; + uint32_t write_block_size = flash_area_align(flash->area); off_t area_offset = flash->offset + block->offset + chunk->offset; - int i = 0; - - /* Write block align the chunk data */ - memset(&buf[i], 0xff, area_offset % WRITE_BLOCK_SIZE); - i += area_offset % WRITE_BLOCK_SIZE; + int start_pad = area_offset % write_block_size; - memcpy(&buf[i], chunk->data, chunk->size); - i += chunk->size; + /* + * Fill buffer with erase value, to make sure only the part of the + * buffer with chunk data will overwrite flash. + * (Because chunks can arrive in random order, this is required unless + * the entire block is cached in RAM). + */ + memset(buf, fparam->erase_value, sizeof(buf)); - memset(&buf[i], 0xff, ROUND_UP(i, WRITE_BLOCK_SIZE) - i); - i = ROUND_UP(i, WRITE_BLOCK_SIZE); + memcpy(&buf[start_pad], chunk->data, chunk->size); return flash_area_write(flash->area, - ROUND_DOWN(area_offset, WRITE_BLOCK_SIZE), - buf, i); + ROUND_DOWN(area_offset, write_block_size), + buf, + ROUND_UP(start_pad + chunk->size, write_block_size)); } int bt_mesh_blob_io_flash_init(struct bt_mesh_blob_io_flash *flash, diff --git a/subsys/bluetooth/mesh/brg_cfg.c b/subsys/bluetooth/mesh/brg_cfg.c index 58d1aada550d..d0bdaef7f05e 100644 --- a/subsys/bluetooth/mesh/brg_cfg.c +++ b/subsys/bluetooth/mesh/brg_cfg.c @@ -52,6 +52,10 @@ static int brg_en_set(const char *name, size_t len_rd, settings_read_cb read_cb, { int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { brg_enabled = 0; LOG_DBG("Cleared bridge enable state"); diff --git a/subsys/bluetooth/mesh/brg_cfg_srv.c b/subsys/bluetooth/mesh/brg_cfg_srv.c index d622ebf48a25..0d0bda534b66 100644 --- a/subsys/bluetooth/mesh/brg_cfg_srv.c +++ b/subsys/bluetooth/mesh/brg_cfg_srv.c @@ -145,60 +145,34 @@ static int bridged_subnets_get(const struct bt_mesh_model *model, struct bt_mesh net_buf_simple_add_le16(&msg, net_idx_filter); net_buf_simple_add_u8(&msg, start_id); - uint8_t cnt = 0; - uint16_t net_idx1, net_idx2; - for (int i = 0; i < rows; i++) { - net_idx1 = brg_tbl[i].net_idx1; - net_idx2 = brg_tbl[i].net_idx2; + uint16_t net_idx1 = brg_tbl[i].net_idx1; + uint16_t net_idx2 = brg_tbl[i].net_idx2; + bool is_first_instance; if (net_buf_simple_tailroom(&msg) < 3 + BT_MESH_MIC_SHORT) { break; } - switch (filter_net_idx.filter) { - /* Report pair of NetKeys from the table, starting from start_id. */ - case 0: - if (i >= start_id) { - key_idx_pack_pair(&msg, net_idx1, net_idx2); + is_first_instance = true; + for (int j = 0; j < i; j++) { + if (net_idx1 == brg_tbl[j].net_idx1 && net_idx2 == brg_tbl[j].net_idx2) { + is_first_instance = false; + break; } - break; - - /* Report pair of NetKeys in which (NetKeyIndex1) matches the net_idx */ - case 1: - if (net_idx1 == filter_net_idx.net_idx) { - if (cnt >= start_id) { - key_idx_pack_pair(&msg, net_idx1, net_idx2); - } - cnt++; - } - break; - - /* Report pair of NetKeys in which (NetKeyIndex2) matches the net_idx */ - case 2: - if (net_idx2 == filter_net_idx.net_idx) { - if (cnt >= start_id) { - key_idx_pack_pair(&msg, net_idx1, net_idx2); - } - cnt++; - } - break; + } - /* Report pair of NetKeys in which (NetKeyIndex1 or NetKeyIndex2) matches the - * net_idx - */ - case 3: - if (net_idx1 == filter_net_idx.net_idx || - net_idx2 == filter_net_idx.net_idx) { - if (cnt >= start_id) { - key_idx_pack_pair(&msg, net_idx1, net_idx2); - } - cnt++; + if (is_first_instance && + (filter_net_idx.filter == 0 || + (filter_net_idx.filter == 1 && net_idx1 == filter_net_idx.net_idx) || + (filter_net_idx.filter == 2 && net_idx2 == filter_net_idx.net_idx) || + (filter_net_idx.filter == 3 && (net_idx1 == filter_net_idx.net_idx || + net_idx2 == filter_net_idx.net_idx)))) { + if (start_id > 0) { + start_id--; + } else { + key_idx_pack_pair(&msg, net_idx1, net_idx2); } - break; - - default: - CODE_UNREACHABLE; } } diff --git a/subsys/bluetooth/mesh/cdb.c b/subsys/bluetooth/mesh/cdb.c index 310108d7b756..dc2725a7a327 100644 --- a/subsys/bluetooth/mesh/cdb.c +++ b/subsys/bluetooth/mesh/cdb.c @@ -180,6 +180,10 @@ static int cdb_net_set(const char *name, size_t len_rd, struct net_val net; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("val (null)"); return 0; @@ -219,6 +223,10 @@ static int cdb_node_set(const char *name, size_t len_rd, uint16_t addr; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; @@ -281,6 +289,10 @@ static int cdb_subnet_set(const char *name, size_t len_rd, uint16_t net_idx; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; @@ -347,6 +359,10 @@ static int cdb_app_key_set(const char *name, size_t len_rd, uint16_t app_idx; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/bluetooth/mesh/cfg.c b/subsys/bluetooth/mesh/cfg.c index 155c2e616d55..e5563b95c3c1 100644 --- a/subsys/bluetooth/mesh/cfg.c +++ b/subsys/bluetooth/mesh/cfg.c @@ -429,6 +429,10 @@ static int cfg_set(const char *name, size_t len_rd, struct cfg_val cfg; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("Cleared configuration state"); return 0; diff --git a/subsys/bluetooth/mesh/heartbeat.c b/subsys/bluetooth/mesh/heartbeat.c index 133c552620f5..0ad4828279c2 100644 --- a/subsys/bluetooth/mesh/heartbeat.c +++ b/subsys/bluetooth/mesh/heartbeat.c @@ -416,6 +416,10 @@ static int hb_pub_set(const char *name, size_t len_rd, struct hb_pub_val hb_val; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + err = bt_mesh_settings_set(read_cb, cb_arg, &hb_val, sizeof(hb_val)); if (err) { LOG_ERR("Failed to set \'hb_val\'"); diff --git a/subsys/bluetooth/mesh/net.c b/subsys/bluetooth/mesh/net.c index 276728bd9a45..d791ba46f9ab 100644 --- a/subsys/bluetooth/mesh/net.c +++ b/subsys/bluetooth/mesh/net.c @@ -82,7 +82,8 @@ struct iv_val { static struct { uint32_t src : 15, /* MSb of source is always 0 */ - seq : 17; + seq : 17; + uint16_t net_idx; } msg_cache[CONFIG_BT_MESH_MSG_CACHE_SIZE]; static uint16_t msg_cache_next; @@ -145,20 +146,22 @@ static bool check_dup(struct net_buf_simple *data) return false; } -static bool msg_cache_match(struct net_buf_simple *pdu) +static bool msg_cache_match(struct net_buf_simple *pdu, uint16_t net_idx) { uint16_t i; for (i = msg_cache_next; i > 0U;) { if (msg_cache[--i].src == SRC(pdu->data) && - msg_cache[i].seq == (SEQ(pdu->data) & BIT_MASK(17))) { + msg_cache[i].seq == (SEQ(pdu->data) & BIT_MASK(17)) && + msg_cache[i].net_idx == net_idx) { return true; } } for (i = ARRAY_SIZE(msg_cache); i > msg_cache_next;) { if (msg_cache[--i].src == SRC(pdu->data) && - msg_cache[i].seq == (SEQ(pdu->data) & BIT_MASK(17))) { + msg_cache[i].seq == (SEQ(pdu->data) & BIT_MASK(17)) && + msg_cache[i].net_idx == net_idx) { return true; } } @@ -171,6 +174,7 @@ static void msg_cache_add(struct bt_mesh_net_rx *rx) msg_cache_next %= ARRAY_SIZE(msg_cache); msg_cache[msg_cache_next].src = rx->ctx.addr; msg_cache[msg_cache_next].seq = rx->seq; + msg_cache[msg_cache_next].net_idx = rx->sub->net_idx; msg_cache_next++; } @@ -653,15 +657,14 @@ static bool net_decrypt(struct bt_mesh_net_rx *rx, struct net_buf_simple *in, return false; } - if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(out)) { + if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(out, rx->sub->net_idx)) { LOG_DBG("Duplicate found in Network Message Cache"); return false; } LOG_DBG("src 0x%04x", rx->ctx.addr); - return bt_mesh_net_decrypt(&cred->enc, out, BT_MESH_NET_IVI_RX(rx), - proxy) == 0; + return bt_mesh_net_decrypt(&cred->enc, out, BT_MESH_NET_IVI_RX(rx), proxy) == 0; } /* Relaying from advertising to the advertising bearer should only happen @@ -1005,6 +1008,10 @@ static int net_set(const char *name, size_t len_rd, settings_read_cb read_cb, struct bt_mesh_key key; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("val (null)"); @@ -1042,6 +1049,10 @@ static int iv_set(const char *name, size_t len_rd, settings_read_cb read_cb, struct iv_val iv; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("IV deleted"); @@ -1074,6 +1085,10 @@ static int seq_set(const char *name, size_t len_rd, settings_read_cb read_cb, struct seq_val seq; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("val (null)"); @@ -1113,6 +1128,10 @@ static int dev_key_cand_set(const char *name, size_t len_rd, settings_read_cb re int err; struct bt_mesh_key key; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (len_rd == 0) { LOG_DBG("val (null)"); diff --git a/subsys/bluetooth/mesh/priv_beacon_srv.c b/subsys/bluetooth/mesh/priv_beacon_srv.c index 8dd1ba3b1d8c..790ffe562835 100644 --- a/subsys/bluetooth/mesh/priv_beacon_srv.c +++ b/subsys/bluetooth/mesh/priv_beacon_srv.c @@ -151,13 +151,14 @@ static int handle_node_id_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - uint8_t node_id, status; + enum bt_mesh_feat_state node_id; uint16_t net_idx; + uint8_t status; net_idx = net_buf_simple_pull_le16(buf) & 0xfff; - status = bt_mesh_subnet_priv_node_id_get(net_idx, (enum bt_mesh_feat_state *)&node_id); - node_id_status_rsp(mod, ctx, status, net_idx, node_id); + status = bt_mesh_subnet_priv_node_id_get(net_idx, &node_id); + node_id_status_rsp(mod, ctx, status, net_idx, (uint8_t)node_id); return 0; } diff --git a/subsys/bluetooth/mesh/prov.c b/subsys/bluetooth/mesh/prov.c index d83485962a13..a5cd8a9fc927 100644 --- a/subsys/bluetooth/mesh/prov.c +++ b/subsys/bluetooth/mesh/prov.c @@ -28,6 +28,9 @@ #include LOG_MODULE_REGISTER(bt_mesh_prov); +/* 10 power 32 represents 14 bytes maximum in little-endian format */ +#define MAX_NUMERIC_OOB_BYTES 14 + struct bt_mesh_prov_link bt_mesh_prov_link; const struct bt_mesh_prov *bt_mesh_prov; @@ -96,7 +99,7 @@ static int check_output_auth(bt_mesh_output_action_t output, uint8_t size) return -EINVAL; } - if (size > bt_mesh_prov->output_size) { + if (size > bt_mesh_prov->output_size || size == 0) { return -EINVAL; } @@ -113,7 +116,7 @@ static int check_input_auth(bt_mesh_input_action_t input, uint8_t size) return -EINVAL; } - if (size > bt_mesh_prov->input_size) { + if (size > bt_mesh_prov->input_size || size == 0) { return -EINVAL; } @@ -122,60 +125,126 @@ static int check_input_auth(bt_mesh_input_action_t input, uint8_t size) static void get_auth_string(char *str, uint8_t size) { - uint64_t value; - - bt_rand(&value, sizeof(value)); - static const char characters[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - for (int i = 0; i < size; i++) { - /* pull base-36 digits: */ - int idx = value % 36; + bt_rand(str, size); - value = value / 36; - str[i] = characters[idx]; + for (int i = 0; i < size; i++) { + str[i] = characters[(uint8_t)str[i] % (uint8_t)36]; } - str[size] = '\0'; - memcpy(bt_mesh_prov_link.auth, str, size); memset(bt_mesh_prov_link.auth + size, 0, sizeof(bt_mesh_prov_link.auth) - size); } -static uint32_t get_auth_number(bt_mesh_output_action_t output, - bt_mesh_input_action_t input, uint8_t size) +/* Computes 10^n - 1 in little endian array */ +static void compute_pow10_minus1(uint8_t n, uint8_t *out, size_t *out_len) { - const uint32_t divider[PROV_IO_OOB_SIZE_MAX] = { 10, 100, 1000, 10000, - 100000, 1000000, 10000000, 100000000 }; - uint8_t auth_size = bt_mesh_prov_auth_size_get(); - uint32_t num = 0; + out[0] = 1; /* Start with value 1 at LSB */ + size_t len = 1; + + /* Compute 10^n */ + for (uint8_t i = 0; i < n; ++i) { + uint16_t carry = 0; + + for (size_t j = 0; j < len; ++j) { + uint16_t prod = out[j] * 10 + carry; + + out[j] = prod & 0xFF; + carry = prod >> 8; + } - bt_rand(&num, sizeof(num)); + if (carry > 0 && len < MAX_NUMERIC_OOB_BYTES) { + out[len] = carry; + len++; + } + } + + /* Subtract 1 from the result (10^n - 1) */ + size_t j = 0; - if (output == BT_MESH_BLINK || output == BT_MESH_BEEP || output == BT_MESH_VIBRATE || - input == BT_MESH_PUSH || input == BT_MESH_TWIST) { - /* According to MshPRTv1.1: 5.4.2.4, blink, beep vibrate, push and twist should be - * a random integer between 0 and 10^size, *exclusive*: - */ - num = (num % (divider[size - 1] - 1)) + 1; - } else { - num %= divider[size - 1]; + while (j < len) { + if (out[j] > 0) { + out[j] -= 1; + break; + } + out[j] = 0xFF; + j++; } - sys_put_be32(num, &bt_mesh_prov_link.auth[auth_size - sizeof(num)]); - memset(bt_mesh_prov_link.auth, 0, auth_size - sizeof(num)); + /* Adjust length if highest byte becomes 0 */ + while (len > 1 && out[len - 1] == 0) { + len--; + } + + *out_len = len; +} + +static void random_byte_shift(uint8_t max_inclusive, uint8_t *out) +{ + if (max_inclusive == 0) { + *out = 0; + return; + } + + while (*out > max_inclusive) { + *out >>= 1; + } +} + +static void generate_random_below_pow10(uint8_t n, uint8_t *output, size_t *out_len) +{ + uint8_t max_val[MAX_NUMERIC_OOB_BYTES] = {0}; + size_t max_len = 0; + + compute_pow10_minus1(n, max_val, &max_len); + bt_rand(output, max_len); + + /* Generate random number less than max_val, starting from MSB in little-endian */ + for (int i = max_len - 1; i >= 0; --i) { + random_byte_shift(max_val[i], &output[i]); + if (output[i] < max_val[i]) { + break; + } + } + + /* Ensure the result is not all zero */ + int all_zero = 1; + + for (size_t i = 0; i < max_len; ++i) { + if (output[i] != 0) { + all_zero = 0; + break; + } + } + + if (all_zero) { + output[0] = 1; + } + + *out_len = max_len; +} + +static void get_auth_number(uint8_t *rand_bytes, size_t *size) +{ + uint8_t auth_size = bt_mesh_prov_auth_size_get(); - return num; + generate_random_below_pow10(*size, rand_bytes, size); + sys_memcpy_swap(bt_mesh_prov_link.auth + (auth_size - *size), rand_bytes, *size); + memset(bt_mesh_prov_link.auth, 0, auth_size - *size); } -int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8_t size) +int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, size_t size) { bt_mesh_output_action_t output; bt_mesh_input_action_t input; + uint8_t rand_bytes[PROV_IO_OOB_SIZE_MAX + 1] = {0}; uint8_t auth_size = bt_mesh_prov_auth_size_get(); int err; + size = MIN(size, PROV_IO_OOB_SIZE_MAX); + switch (method) { case AUTH_METHOD_NO_OOB: if (action || size) { @@ -195,6 +264,10 @@ int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8 case AUTH_METHOD_OUTPUT: output = output_action(action); + err = check_output_auth(output, size); + if (err) { + return err; + } if (is_provisioner) { if (output == BT_MESH_DISPLAY_STRING) { @@ -208,32 +281,31 @@ int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8 return bt_mesh_prov->input(input, size); } - err = check_output_auth(output, size); - if (err) { - return err; - } + atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); if (output == BT_MESH_DISPLAY_STRING) { - char str[9]; - - atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); - get_auth_string(str, size); - return bt_mesh_prov->output_string(str); + get_auth_string(rand_bytes, MIN(size, auth_size)); + return bt_mesh_prov->output_string(rand_bytes); } - atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); - return bt_mesh_prov->output_number(output, - get_auth_number(output, BT_MESH_NO_INPUT, size)); + get_auth_number(rand_bytes, &size); +#if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY + uint32_t output_num; + + memcpy(&output_num, rand_bytes, sizeof(output_num)); + return bt_mesh_prov->output_number(output, output_num); +#else + return bt_mesh_prov->output_numeric(output, rand_bytes, size); +#endif case AUTH_METHOD_INPUT: input = input_action(action); + err = check_input_auth(input, size); + if (err) { + return err; + } if (!is_provisioner) { - err = check_input_auth(input, size); - if (err) { - return err; - } - if (input == BT_MESH_ENTER_STRING) { atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING); } else { @@ -243,24 +315,30 @@ int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8 return bt_mesh_prov->input(input, size); } - if (input == BT_MESH_ENTER_STRING) { - char str[9]; + atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); - atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); - get_auth_string(str, size); - return bt_mesh_prov->output_string(str); + if (input == BT_MESH_ENTER_STRING) { + get_auth_string(rand_bytes, MIN(size, auth_size)); + return bt_mesh_prov->output_string(rand_bytes); } - atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); + get_auth_number(rand_bytes, &size); output = BT_MESH_DISPLAY_NUMBER; - return bt_mesh_prov->output_number(output, - get_auth_number(BT_MESH_NO_OUTPUT, input, size)); +#if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY + uint32_t input_num; + + memcpy(&input_num, rand_bytes, sizeof(input_num)); + return bt_mesh_prov->output_number(output, input_num); +#else + return bt_mesh_prov->output_numeric(output, rand_bytes, size); +#endif default: return -EINVAL; } } +#if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY int bt_mesh_input_number(uint32_t num) { uint8_t auth_size = bt_mesh_prov_auth_size_get(); @@ -277,13 +355,37 @@ int bt_mesh_input_number(uint32_t num) return 0; } +#endif + +int bt_mesh_input_numeric(uint8_t *numeric, size_t size) +{ + uint8_t auth_size = bt_mesh_prov_auth_size_get(); + + LOG_HEXDUMP_DBG(numeric, size, ""); + + if (size > MAX_NUMERIC_OOB_BYTES) { + return -ENOTSUP; + } + + if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_NUMBER)) { + return -EINVAL; + } + + sys_memcpy_swap(bt_mesh_prov_link.auth + (auth_size - size), numeric, size); + memset(bt_mesh_prov_link.auth, 0, auth_size - size); + + bt_mesh_prov_link.role->input_complete(); + + return 0; +} int bt_mesh_input_string(const char *str) { + size_t size = strlen(str); + LOG_DBG("%s", str); - if (strlen(str) > PROV_IO_OOB_SIZE_MAX || - strlen(str) > bt_mesh_prov_link.oob_size) { + if (size > PROV_IO_OOB_SIZE_MAX || size > bt_mesh_prov_link.oob_size) { return -ENOTSUP; } @@ -291,7 +393,8 @@ int bt_mesh_input_string(const char *str) return -EINVAL; } - memcpy(bt_mesh_prov_link.auth, str, strlen(str)); + memcpy(bt_mesh_prov_link.auth, str, size); + memset(bt_mesh_prov_link.auth + size, 0, sizeof(bt_mesh_prov_link.auth) - size); bt_mesh_prov_link.role->input_complete(); diff --git a/subsys/bluetooth/mesh/prov.h b/subsys/bluetooth/mesh/prov.h index 00bd85952e0e..499b1ca60359 100644 --- a/subsys/bluetooth/mesh/prov.h +++ b/subsys/bluetooth/mesh/prov.h @@ -68,7 +68,11 @@ #define PROV_ALG_P256 0x00 +#if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY #define PROV_IO_OOB_SIZE_MAX 8 /* in bytes */ +#else +#define PROV_IO_OOB_SIZE_MAX 32 /* in bytes */ +#endif #define PRIV_KEY_SIZE 32 #define PUB_KEY_SIZE PDU_LEN_PUB_KEY @@ -164,10 +168,14 @@ static inline void bt_mesh_prov_buf_init(struct net_buf_simple *buf, uint8_t typ net_buf_simple_add_u8(buf, type); } - static inline uint8_t bt_mesh_prov_auth_size_get(void) { - return bt_mesh_prov_link.algorithm == BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM ? 16 : 32; + if (IS_ENABLED(CONFIG_BT_MESH_ECDH_P256_HMAC_SHA256_AES_CCM)) { + return bt_mesh_prov_link.algorithm == BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM ? 16 + : 32; + } else { + return 16; + } } static inline k_timeout_t bt_mesh_prov_protocol_timeout_get(void) @@ -182,7 +190,7 @@ int bt_mesh_prov_reset_state(void); bool bt_mesh_prov_active(void); -int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8_t size); +int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, size_t size); int bt_mesh_pb_remote_open(struct bt_mesh_rpr_cli *cli, const struct bt_mesh_rpr_node *srv, const uint8_t uuid[16], diff --git a/subsys/bluetooth/mesh/provisioner.c b/subsys/bluetooth/mesh/provisioner.c index b1df6431d068..efc480b74ef3 100644 --- a/subsys/bluetooth/mesh/provisioner.c +++ b/subsys/bluetooth/mesh/provisioner.c @@ -172,8 +172,12 @@ static bool prov_check_method(struct bt_mesh_dev_capabilities *caps) return false; } } else { +#if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY if (!bt_mesh_prov->output_number) { - LOG_WRN("Not support output number"); +#else + if (!bt_mesh_prov->output_numeric) { +#endif + LOG_WRN("Not support output numeric"); return false; } } @@ -577,10 +581,9 @@ static void prov_complete(const uint8_t *data) bt_hex(&provisionee.new_dev_key, 16), node->net_idx, node->num_elem, node->addr); - bt_mesh_prov_link.expect = PROV_NO_PDU; atomic_set_bit(bt_mesh_prov_link.flags, COMPLETE); - bt_mesh_prov_link.bearer->link_close(PROV_BEARER_LINK_STATUS_SUCCESS); + prov_link_close(PROV_BEARER_LINK_STATUS_SUCCESS); } static void prov_node_add(void) @@ -685,7 +688,7 @@ static void prov_confirm(const uint8_t *data) static void prov_failed(const uint8_t *data) { LOG_WRN("Error: 0x%02x", data[0]); - reset_state(); + prov_link_close(PROV_BEARER_LINK_STATUS_FAIL); } static void local_input_complete(void) diff --git a/subsys/bluetooth/mesh/rpl.c b/subsys/bluetooth/mesh/rpl.c index 581c94771c81..7c9317fcc94c 100644 --- a/subsys/bluetooth/mesh/rpl.c +++ b/subsys/bluetooth/mesh/rpl.c @@ -272,6 +272,10 @@ static int rpl_set(const char *name, size_t len_rd, int err; uint16_t src; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/bluetooth/mesh/shell/shell.c b/subsys/bluetooth/mesh/shell/shell.c index 5475cc5d49b4..10138b164ad7 100644 --- a/subsys/bluetooth/mesh/shell/shell.c +++ b/subsys/bluetooth/mesh/shell/shell.c @@ -25,6 +25,7 @@ #include "mesh/foundation.h" #include "mesh/settings.h" #include "mesh/access.h" +#include "mesh/prov.h" #include "common/bt_shell_private.h" #include "utils.h" #include "dfu.h" @@ -399,18 +400,59 @@ static int cmd_proxy_solicit(const struct shell *sh, size_t argc, #endif /* CONFIG_BT_MESH_SHELL_GATT_PROXY */ #if defined(CONFIG_BT_MESH_SHELL_PROV) +static int ascii_decimal_to_le_bytes(const char *ascii_str, uint8_t *out, size_t *out_len) +{ + size_t len = 0; + + for (const char *p = ascii_str; *p; ++p) { + if (!isdigit((unsigned char)*p)) { + return -EINVAL; /* Invalid character */ + } + + uint16_t carry = *p - '0'; + + /* If this is the first digit and it's 0, we need at least one byte */ + if (len == 0) { + out[0] = carry; + len = 1; + continue; + } + + /* Multiply current result by 10 and add new digit */ + for (size_t i = 0; i < len; ++i) { + uint16_t value = out[i] * 10 + carry; + + out[i] = value & 0xFF; + carry = value >> 8; + } + + /* Handle overflow to next byte */ + if (carry != 0) { + if (len >= PROV_IO_OOB_SIZE_MAX) { + return -EOVERFLOW; /* Overflow */ + } + out[len++] = carry; + } + } + + *out_len = len; + return 0; +} + static int cmd_input_num(const struct shell *sh, size_t argc, char *argv[]) { int err = 0; - uint32_t val; + uint8_t result[PROV_IO_OOB_SIZE_MAX] = {0}; + size_t result_len; - val = shell_strtoul(argv[1], 10, &err); + err = ascii_decimal_to_le_bytes(argv[1], result, &result_len); if (err) { - shell_warn(sh, "Unable to parse input string argument"); + shell_warn(sh, err == -EINVAL ? "The input string symbol is not a digit" + : "Overflow in input string argument"); return err; } - err = bt_mesh_input_number(val); + err = bt_mesh_input_numeric(result, result_len); if (err) { shell_error(sh, "Numeric input failed (err %d)", err); } @@ -523,30 +565,76 @@ static void prov_reset(void) bt_shell_print("The local node has been reset and needs reprovisioning"); } -static int output_number(bt_mesh_output_action_t action, uint32_t number) +static void binary_to_ascii_digits(const uint8_t *in, size_t in_len, char *out_str) { + uint8_t temp[PROV_IO_OOB_SIZE_MAX]; + size_t digit_count = 0; + + __ASSERT(in_len <= sizeof(temp), "Output numeric exceeds maximum"); + memcpy(temp, in, in_len); + + while (in_len > 0) { + uint16_t remainder = 0; + + /* Divide the number in `temp` by 10, store quotient back in `temp` */ + for (ssize_t i = in_len - 1; i >= 0; --i) { + uint16_t acc = ((uint16_t)remainder << 8) | temp[i]; + + temp[i] = acc / 10; + remainder = acc % 10; + } + + /* Store ASCII digit */ + out_str[digit_count++] = '0' + remainder; + + /* Trim leading zeros */ + while (in_len > 0 && temp[in_len - 1] == 0) { + in_len--; + } + } + + /* Digits are in reverse order, reverse them to get correct string */ + sys_mem_swap(out_str, digit_count); + + /* Null-terminate the string */ + out_str[digit_count] = '\0'; +} + +static int output_numeric(bt_mesh_output_action_t action, uint8_t *numeric, size_t len) +{ + char oob_string[PROV_IO_OOB_SIZE_MAX + 1]; + + binary_to_ascii_digits(numeric, len, oob_string); + switch (action) { case BT_MESH_BLINK: - bt_shell_print("OOB blink Number: %u", number); + bt_shell_print("OOB blink Number: %s", oob_string); break; case BT_MESH_BEEP: - bt_shell_print("OOB beep Number: %u", number); + bt_shell_print("OOB beep Number: %s", oob_string); break; case BT_MESH_VIBRATE: - bt_shell_print("OOB vibrate Number: %u", number); + bt_shell_print("OOB vibrate Number: %s", oob_string); break; case BT_MESH_DISPLAY_NUMBER: - bt_shell_print("OOB display Number: %u", number); + bt_shell_print("OOB display Number: %s", oob_string); break; default: - bt_shell_error("Unknown Output action %u (number %u) requested!", - action, number); + bt_shell_error("Unknown Output action %u (number %s) requested!", action, + oob_string); return -EINVAL; } return 0; } +#if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY +static int output_number(bt_mesh_output_action_t action, uint32_t number) +{ + return output_numeric(action, (uint8_t *)&number, sizeof(number)); +} +#endif + static int output_string(const char *str) { bt_shell_print("OOB String: %s", str); @@ -602,7 +690,11 @@ struct bt_mesh_prov bt_mesh_shell_prov = { .output_size = 6, .output_actions = (BT_MESH_BLINK | BT_MESH_BEEP | BT_MESH_VIBRATE | BT_MESH_DISPLAY_NUMBER | BT_MESH_DISPLAY_STRING), +#if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY .output_number = output_number, +#else + .output_numeric = output_numeric, +#endif .output_string = output_string, .input_size = 6, .input_actions = diff --git a/subsys/bluetooth/mesh/solicitation.c b/subsys/bluetooth/mesh/solicitation.c index a2872daecb03..2d863dc57dc5 100644 --- a/subsys/bluetooth/mesh/solicitation.c +++ b/subsys/bluetooth/mesh/solicitation.c @@ -120,6 +120,10 @@ static int sseq_set(const char *name, size_t len_rd, { int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + err = bt_mesh_settings_set(read_cb, cb_arg, &sseq_out, sizeof(sseq_out)); if (err) { LOG_ERR("Failed to set \'sseq\'"); @@ -365,6 +369,10 @@ static int srpl_set(const char *name, size_t len_rd, } } + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + err = bt_mesh_settings_set(read_cb, cb_arg, &sseq, sizeof(sseq)); if (err) { LOG_ERR("Failed to set \'sseq\'"); diff --git a/subsys/bluetooth/mesh/subnet.c b/subsys/bluetooth/mesh/subnet.c index b17b9a497400..7f2943365976 100644 --- a/subsys/bluetooth/mesh/subnet.c +++ b/subsys/bluetooth/mesh/subnet.c @@ -971,6 +971,10 @@ static int net_key_set(const char *name, size_t len_rd, int err; uint16_t net_idx; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/bluetooth/mesh/va.c b/subsys/bluetooth/mesh/va.c index fb81f36251cf..0b83e93e1c8d 100644 --- a/subsys/bluetooth/mesh/va.c +++ b/subsys/bluetooth/mesh/va.c @@ -219,6 +219,10 @@ static int va_set(const char *name, size_t len_rd, uint16_t index; int err; + if (!IS_ENABLED(CONFIG_BT_SETTINGS)) { + return 0; + } + if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; diff --git a/subsys/bluetooth/services/CMakeLists.txt b/subsys/bluetooth/services/CMakeLists.txt index bb69916e301a..f17f683d7186 100644 --- a/subsys/bluetooth/services/CMakeLists.txt +++ b/subsys/bluetooth/services/CMakeLists.txt @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_sources_ifdef(CONFIG_BT_ANS ans.c) zephyr_sources_ifdef(CONFIG_BT_DIS dis.c) diff --git a/subsys/bluetooth/services/Kconfig b/subsys/bluetooth/services/Kconfig index a57d4998f380..cad7dc5a7258 100644 --- a/subsys/bluetooth/services/Kconfig +++ b/subsys/bluetooth/services/Kconfig @@ -6,6 +6,8 @@ menu "GATT Services" depends on BT_CONN +rsource "Kconfig.ans" + rsource "Kconfig.dis" rsource "Kconfig.cts" diff --git a/subsys/bluetooth/services/Kconfig.ans b/subsys/bluetooth/services/Kconfig.ans new file mode 100644 index 000000000000..e54adb0f76e5 --- /dev/null +++ b/subsys/bluetooth/services/Kconfig.ans @@ -0,0 +1,86 @@ +# Bluetooth GATT Alert Notification Service + +# Copyright (c) 2025 Sean Kyer +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig BT_ANS + bool "GATT Alert Notification Service [EXPERIMENTAL]" + depends on UTF8 + select EXPERIMENTAL + +if BT_ANS + +module = BT_ANS +module-str = Alert Notification Service (ANS) +source "subsys/logging/Kconfig.template.log_config" + +menu "New Alert Categories" + +config BT_ANS_NALRT_CAT_SIMPLE_ALERT + bool "Support Simple Alert" + +config BT_ANS_NALRT_CAT_EMAIL + bool "Support Email" + +config BT_ANS_NALRT_CAT_NEWS + bool "Support News" + +config BT_ANS_NALRT_CAT_CALL + bool "Support Call" + +config BT_ANS_NALRT_CAT_MISSED_CALL + bool "Support Missed Call" + +config BT_ANS_NALRT_CAT_SMS_MMS + bool "Support SMS/MMS" + +config BT_ANS_NALRT_CAT_VOICE_MAIL + bool "Support Voice Mail" + +config BT_ANS_NALRT_CAT_SCHEDULE + bool "Support Schedule" + +config BT_ANS_NALRT_CAT_HIGH_PRI_ALERT + bool "Support High Priority Alert" + +config BT_ANS_NALRT_CAT_INSTANT_MESSAGE + bool "Support Instant Message" + +endmenu + +menu "Unread Alert Categories" + +config BT_ANS_UNALRT_CAT_SIMPLE_ALERT + bool "Support Simple Alert" + +config BT_ANS_UNALRT_CAT_EMAIL + bool "Support Email" + +config BT_ANS_UNALRT_CAT_NEWS + bool "Support News" + +config BT_ANS_UNALRT_CAT_CALL + bool "Support Call" + +config BT_ANS_UNALRT_CAT_MISSED_CALL + bool "Support Missed Call" + +config BT_ANS_UNALRT_CAT_SMS_MMS + bool "Support SMS/MMS" + +config BT_ANS_UNALRT_CAT_VOICE_MAIL + bool "Support Voice Mail" + +config BT_ANS_UNALRT_CAT_SCHEDULE + bool "Support Schedule" + +config BT_ANS_UNALRT_CAT_HIGH_PRI_ALERT + bool "Support High Priority Alert" + +config BT_ANS_UNALRT_CAT_INSTANT_MESSAGE + bool "Support Instant Message" + +endmenu + +endif # BT_ANS diff --git a/subsys/bluetooth/services/ans.c b/subsys/bluetooth/services/ans.c new file mode 100644 index 000000000000..418c90bc1141 --- /dev/null +++ b/subsys/bluetooth/services/ans.c @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2025 Sean Kyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * https://www.bluetooth.com/specifications/specs/alert-notification-service-1-0/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(bt_ans, CONFIG_BT_ANS_LOG_LEVEL); + +/* + * This only enforces a necessary lower bound at build time. It does + * not guarantee that notification/transmit operations will never fail at + * runtime because other subsystems/services can hold outstanding ATT + * buffers concurrently. + */ +BUILD_ASSERT(CONFIG_BT_MAX_CONN <= CONFIG_BT_ATT_TX_COUNT, + "CONFIG_BT_ATT_TX_COUNT must be >= CONFIG_BT_MAX_CONN"); + +/* Build time ANS supported category bit mask */ +#define BT_ANS_NALRT_CAT_MASK \ + ((IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_SIMPLE_ALERT) << BT_ANS_CAT_SIMPLE_ALERT) | \ + (IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_EMAIL) << BT_ANS_CAT_EMAIL) | \ + (IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_NEWS) << BT_ANS_CAT_NEWS) | \ + (IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_CALL) << BT_ANS_CAT_CALL) | \ + (IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_MISSED_CALL) << BT_ANS_CAT_MISSED_CALL) | \ + (IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_SMS_MMS) << BT_ANS_CAT_SMS_MMS) | \ + (IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_VOICE_MAIL) << BT_ANS_CAT_VOICE_MAIL) | \ + (IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_SCHEDULE) << BT_ANS_CAT_SCHEDULE) | \ + (IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_HIGH_PRI_ALERT) << BT_ANS_CAT_HIGH_PRI_ALERT) | \ + (IS_ENABLED(CONFIG_BT_ANS_NALRT_CAT_INSTANT_MESSAGE) << BT_ANS_CAT_INSTANT_MESSAGE)) + +/* Build time ANS supported category bit mask */ +#define BT_ANS_UNALRT_CAT_MASK \ + ((IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_SIMPLE_ALERT) << BT_ANS_CAT_SIMPLE_ALERT) | \ + (IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_EMAIL) << BT_ANS_CAT_EMAIL) | \ + (IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_NEWS) << BT_ANS_CAT_NEWS) | \ + (IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_CALL) << BT_ANS_CAT_CALL) | \ + (IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_MISSED_CALL) << BT_ANS_CAT_MISSED_CALL) | \ + (IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_SMS_MMS) << BT_ANS_CAT_SMS_MMS) | \ + (IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_VOICE_MAIL) << BT_ANS_CAT_VOICE_MAIL) | \ + (IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_SCHEDULE) << BT_ANS_CAT_SCHEDULE) | \ + (IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_HIGH_PRI_ALERT) << BT_ANS_CAT_HIGH_PRI_ALERT) | \ + (IS_ENABLED(CONFIG_BT_ANS_UNALRT_CAT_INSTANT_MESSAGE) << BT_ANS_CAT_INSTANT_MESSAGE)) + +/* As per spec, ensure at least one New Alert category is supported */ +BUILD_ASSERT(BT_ANS_NALRT_CAT_MASK != 0, + "At least one ANS New Alert category must be enabled in Kconfig"); + +static uint16_t alert_sup_cat_bit_mask = BT_ANS_NALRT_CAT_MASK; +static uint16_t unread_sup_cat_bit_mask = BT_ANS_UNALRT_CAT_MASK; + +/* Command ID definitions */ +#define BT_ANS_SEND_ALL_CATEGORY 0xFF +enum bt_ans_command_id { + BT_ANS_CTRL_ENABLE_NEW_ALERT, + BT_ANS_CTRL_ENABLE_UNREAD, + BT_ANS_CTRL_DISABLE_NEW_ALERT, + BT_ANS_CTRL_DISABLE_UNREAD, + BT_ANS_CTRL_NOTIFY_NEW_ALERT_IMMEDIATE, + BT_ANS_CTRL_NOTIFY_UNREAD_IMMEDIATE, +}; + +/* Struct definition for Alert Notification Control Point */ +struct alert_ctrl_p { + uint8_t cmd_id; + uint8_t category; +} __packed; + +/* Struct definition for New Alert */ +struct new_alert { + uint8_t category_id; + uint8_t num_new_alerts; + char text_string[BT_ANS_MAX_TEXT_STR_SIZE + 1]; +} __packed; + +/* Struct definition for Unread Alert */ +struct unread_alert_status { + uint8_t category_id; + uint8_t unread_count; +} __packed; + +/* Mutex for modifying database */ +K_MUTEX_DEFINE(new_alert_mutex); +K_MUTEX_DEFINE(unread_mutex); + +/* Saved messages database */ +static struct new_alert new_alerts[BT_ANS_CAT_NUM]; +static struct unread_alert_status unread_alerts[BT_ANS_CAT_NUM]; + +/* Initialize to 0, it is control point responsibility to enable once connected */ +static uint16_t alert_cat_enabled_map; +static uint16_t unread_cat_enabled_map; + +/* Supported New Alert Category */ +static ssize_t read_supp_new_alert_cat(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset) +{ + LOG_DBG("Supported New Alert Category Read"); + + /* Return the bit mask of the supported categories */ + return bt_gatt_attr_read(conn, attr, buf, len, offset, &alert_sup_cat_bit_mask, + sizeof(alert_sup_cat_bit_mask)); +} + +/* New Alert Notifications */ +static void new_alert_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) +{ + ARG_UNUSED(attr); + + LOG_DBG("New Alert Notifications %s", value == BT_GATT_CCC_NOTIFY ? "enabled" : "disabled"); +} + +/* Supported Unread Alert Category*/ +static ssize_t read_supp_unread_alert_cat(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset) +{ + LOG_DBG("Supported Unread Alert Category Read"); + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &unread_sup_cat_bit_mask, + sizeof(unread_sup_cat_bit_mask)); +} + +/* Unread Alert Status Notifications */ +static void unread_alert_status_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) +{ + ARG_UNUSED(attr); + + LOG_DBG("Unread Alert Status Notifications %s", + value == BT_GATT_CCC_NOTIFY ? "enabled" : "disabled"); +} + +/* Alert Notification Control Point */ +static int transmit_new_alert(struct bt_conn *conn, enum bt_ans_cat category); +static int transmit_unread_alert(struct bt_conn *conn, enum bt_ans_cat category); +static ssize_t write_alert_notif_ctrl_point(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, uint16_t offset, + uint8_t flags) +{ + int rc; + + LOG_DBG("Alert Control Point Written %u", len); + + if (len != sizeof(struct alert_ctrl_p)) { + LOG_DBG("Length of control packet is %u when expected %zu", len, + sizeof(struct alert_ctrl_p)); + return BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP); + } + + struct alert_ctrl_p command = *((const struct alert_ctrl_p *)buf); + + LOG_DBG("Command ID 0x%x", command.cmd_id); + LOG_DBG("Category 0x%x", command.category); + + if (command.category >= BT_ANS_CAT_NUM && command.category != BT_ANS_SEND_ALL_CATEGORY) { + LOG_DBG("Received control point request for category out of bounds: %d", + command.category); + return BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP); + } + + /* + * If category is BT_ANS_SEND_ALL_CATEGORY then only BT_ANS_CTRL_NOTIFY_NEW_ALERT_IMMEDIATE + * or BT_ANS_CTRL_NOTIFY_UNREAD_IMMEDIATE are valid command IDs + */ + if (command.category == BT_ANS_SEND_ALL_CATEGORY) { + switch (command.cmd_id) { + case BT_ANS_CTRL_NOTIFY_NEW_ALERT_IMMEDIATE: + rc = transmit_new_alert(conn, command.category); + return rc ? BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP) : len; + case BT_ANS_CTRL_NOTIFY_UNREAD_IMMEDIATE: + rc = transmit_unread_alert(conn, command.category); + return rc ? BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP) : len; + default: + return BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP); + } + } + + switch (command.cmd_id) { + case BT_ANS_CTRL_ENABLE_NEW_ALERT: + if ((alert_sup_cat_bit_mask & (1U << command.category)) == 0) { + LOG_DBG("Received control point request for unsupported category: " + "%d", + command.category); + return BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP); + } + alert_cat_enabled_map |= (1U << command.category); + break; + case BT_ANS_CTRL_ENABLE_UNREAD: + if ((unread_sup_cat_bit_mask & (1U << command.category)) == 0) { + LOG_DBG("Received control point request for unsupported category: " + "%d", + command.category); + return BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP); + } + unread_cat_enabled_map |= (1U << command.category); + break; + case BT_ANS_CTRL_DISABLE_NEW_ALERT: + if ((alert_sup_cat_bit_mask & (1U << command.category)) == 0) { + LOG_DBG("Received control point request for unsupported category: " + "%d", + command.category); + + return BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP); + } + alert_cat_enabled_map &= ~(1U << command.category); + break; + case BT_ANS_CTRL_DISABLE_UNREAD: + if ((unread_sup_cat_bit_mask & (1U << command.category)) == 0) { + LOG_DBG("Received control point request for unsupported category: " + "%d", + command.category); + return BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP); + } + unread_cat_enabled_map &= ~(1U << command.category); + break; + default: + return BT_GATT_ERR(BT_ANS_ERR_CMD_NOT_SUP); + } + + return len; +} + +static int ans_init(void) +{ + for (int i = 0; i < BT_ANS_CAT_NUM; i++) { + new_alerts[i].category_id = i; + unread_alerts[i].category_id = i; + } + + LOG_INF("ANS initialization complete"); + + return 0; +} + +/* Alert Notification Service Declaration */ +BT_GATT_SERVICE_DEFINE( + ans_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_ANS), + BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SNALRTC, BT_GATT_CHRC_READ, BT_GATT_PERM_READ, + read_supp_new_alert_cat, NULL, NULL), + BT_GATT_CHARACTERISTIC(BT_UUID_GATT_NALRT, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE, NULL, + NULL, NULL), + BT_GATT_CCC(new_alert_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), + BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SUALRTC, BT_GATT_CHRC_READ, BT_GATT_PERM_READ, + read_supp_unread_alert_cat, NULL, NULL), + BT_GATT_CHARACTERISTIC(BT_UUID_GATT_UALRTS, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE, NULL, + NULL, NULL), + BT_GATT_CCC(unread_alert_status_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), + BT_GATT_CHARACTERISTIC(BT_UUID_GATT_ALRTNCP, BT_GATT_CHRC_WRITE, BT_GATT_PERM_WRITE, NULL, + write_alert_notif_ctrl_point, NULL)); + +/* Helper to notify a single category */ +static int notify_new_alert_category(struct bt_conn *conn, uint8_t cat) +{ + int rc; + int ret; + + ret = k_mutex_lock(&new_alert_mutex, K_NO_WAIT); + if (ret != 0) { + LOG_ERR("Unable to lock mutex (err: %d)", ret); + return -EAGAIN; + } + + rc = bt_gatt_notify_uuid(conn, BT_UUID_GATT_NALRT, ans_svc.attrs, &new_alerts[cat], + sizeof(struct new_alert)); + + ret = k_mutex_unlock(&new_alert_mutex); + __ASSERT(ret == 0, "Unable to unlock mutex (err: %d)", ret); + + /* If the client is not connected, that is fine */ + if (rc != 0 && rc != -ENOTCONN) { + LOG_DBG("Error notifying New Alert category %d rc: %d", cat, rc); + return rc; + } + + return 0; +} + +/* Transmit New Alert */ +static int transmit_new_alert(struct bt_conn *conn, enum bt_ans_cat category) +{ + int rc; + + uint8_t cat_in = (uint8_t)category; + + /* Nothing to do if notify is disabled */ + if (conn != NULL && !bt_gatt_is_subscribed(conn, &ans_svc.attrs[3], BT_GATT_CCC_NOTIFY)) { + return 0; + } + + /* Special case: send all categories */ + if (cat_in == BT_ANS_SEND_ALL_CATEGORY) { + for (int i = 0; i < BT_ANS_CAT_NUM; i++) { + if (((alert_sup_cat_bit_mask & BIT(i)) != 0) && + ((alert_cat_enabled_map & BIT(i)) != 0)) { + rc = notify_new_alert_category(conn, i); + if (rc < 0) { + return rc; + } + } + } + return 0; + } + + /* Otherwise send just the requested category (if enabled) */ + if ((alert_cat_enabled_map & BIT(cat_in)) != 0) { + return notify_new_alert_category(conn, cat_in); + } + + return 0; +} + +/* Helper to notify a single unread alert category */ +static int notify_unread_alert_category(struct bt_conn *conn, uint8_t cat) +{ + int rc; + int ret; + + ret = k_mutex_lock(&unread_mutex, K_NO_WAIT); + if (ret != 0) { + LOG_ERR("Unable to lock mutex (err: %d)", ret); + return -EAGAIN; + } + + rc = bt_gatt_notify_uuid(conn, BT_UUID_GATT_UALRTS, ans_svc.attrs, &unread_alerts[cat], + sizeof(struct unread_alert_status)); + + ret = k_mutex_unlock(&unread_mutex); + __ASSERT(ret == 0, "Unable to unlock mutex (err: %d)", ret); + + /* If the client is not connected, that is fine */ + if (rc != 0 && rc != -ENOTCONN) { + LOG_DBG("Error notifying Unread Alert category %d rc: %d", cat, rc); + return rc; + } + + return 0; +} + +/* Transmit Unread Alert */ +static int transmit_unread_alert(struct bt_conn *conn, enum bt_ans_cat category) +{ + int rc; + + uint8_t cat_in = (uint8_t)category; + + /* Nothing to do if notify is disabled */ + if (conn != NULL && !bt_gatt_is_subscribed(conn, &ans_svc.attrs[6], BT_GATT_CCC_NOTIFY)) { + return 0; + } + + /* Special case: send all categories */ + if (cat_in == BT_ANS_SEND_ALL_CATEGORY) { + for (int i = 0; i < BT_ANS_CAT_NUM; i++) { + if ((unread_sup_cat_bit_mask & BIT(i)) && + (unread_cat_enabled_map & BIT(i))) { + rc = notify_unread_alert_category(conn, i); + if (rc < 0) { + return rc; + } + } + } + return 0; + } + + /* Otherwise send just the requested category (if enabled) */ + if ((unread_cat_enabled_map & BIT(cat_in)) != 0) { + return notify_unread_alert_category(conn, cat_in); + } + + return 0; +} + +int bt_ans_notify_new_alert(struct bt_conn *conn, enum bt_ans_cat category, uint8_t num_new, + const char *text) +{ + int ret; + + uint8_t cat_in = (uint8_t)category; + + /* Check if the category is supported */ + if ((alert_sup_cat_bit_mask & (1U << cat_in)) == 0) { + LOG_DBG("Category %d unsupported", cat_in); + return -EINVAL; + } + + /* Update the saved value */ + ret = k_mutex_lock(&new_alert_mutex, K_FOREVER); + __ASSERT(ret == 0, "Unable to lock mutex (err: %d)", ret); + new_alerts[cat_in].num_new_alerts = num_new; + utf8_lcpy(new_alerts[cat_in].text_string, text, sizeof(new_alerts[cat_in].text_string)); + ret = k_mutex_unlock(&new_alert_mutex); + __ASSERT(ret == 0, "Unable to unlock mutex (err: %d)", ret); + + return transmit_new_alert(conn, category); +} + +int bt_ans_set_unread_count(struct bt_conn *conn, enum bt_ans_cat category, uint8_t unread) +{ + int ret; + + uint8_t cat_in = (uint8_t)category; + + /* Check if the category is supported */ + if ((unread_sup_cat_bit_mask & (1U << cat_in)) == 0) { + LOG_DBG("Category %d unsupported", cat_in); + return -EINVAL; + } + + /* Update the saved value */ + ret = k_mutex_lock(&unread_mutex, K_FOREVER); + __ASSERT(ret == 0, "Unable to lock mutex (err: %d)", ret); + unread_alerts[cat_in].unread_count = unread; + ret = k_mutex_unlock(&unread_mutex); + __ASSERT(ret == 0, "Unable to unlock mutex (err: %d)", ret); + + return transmit_unread_alert(conn, category); +} + +/* Callback used by bt_conn_foreach() to detect an established connection. */ +static void ans_conn_check_cb(struct bt_conn *conn, void *data) +{ + int err; + bool *has_conn = data; + struct bt_conn_info info; + + err = bt_conn_get_info(conn, &info); + if (err == 0 && info.state == BT_CONN_STATE_CONNECTED) { + *has_conn = true; + } +} + +/* Used to check if an active connect exists, stopping modifications to supported features */ +static bool ans_check_conn_busy(void) +{ + bool has_conn = false; + + bt_conn_foreach(BT_CONN_TYPE_ALL, ans_conn_check_cb, &has_conn); + + if (has_conn) { + /* Cannot change support while connection exists */ + return true; + } + + return false; +} + +int bt_ans_set_new_alert_support_category(uint16_t mask) +{ + if (ans_check_conn_busy()) { + /* Cannot change support while connection exists */ + return -EBUSY; + } + + alert_sup_cat_bit_mask = mask; + + LOG_DBG("New Alert Support Bit Mask: %x", alert_sup_cat_bit_mask); + + return 0; +} + +int bt_ans_set_unread_support_category(uint16_t mask) +{ + if (ans_check_conn_busy()) { + /* Cannot change support while connection exists */ + return -EBUSY; + } + + unread_sup_cat_bit_mask = mask; + + LOG_DBG("Unread Support Bit Mask: %x", unread_sup_cat_bit_mask); + + return 0; +} + +SYS_INIT(ans_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/subsys/dfu/boot/mcuboot.c b/subsys/dfu/boot/mcuboot.c index ad8ade044d41..70c746cf7ce1 100644 --- a/subsys/dfu/boot/mcuboot.c +++ b/subsys/dfu/boot/mcuboot.c @@ -58,8 +58,49 @@ enum IMAGE_INDEXES { IMAGE_INDEX_2 }; -#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) || \ - defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT) +#if USE_PARTITION_MANAGER +#include + +#if CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER != -1 +/* Sysbuild */ +#ifdef CONFIG_MCUBOOT +/* lib is part of MCUboot -> operate on the primary application slot */ +#define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_PRIMARY_ID +#else +/* TODO: Add firmware loader support */ +/* lib is part of the app -> operate on active slot */ +#if defined(CONFIG_NCS_IS_VARIANT_IMAGE) +#define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_SECONDARY_ID +#else +#define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_PRIMARY_ID +#endif +#endif /* CONFIG_MCUBOOT */ +#else +/* Legacy child/parent */ +#if CONFIG_BUILD_WITH_TFM + #define PM_ADDRESS_OFFSET (PM_MCUBOOT_PAD_SIZE + PM_TFM_SIZE) +#else + #define PM_ADDRESS_OFFSET (PM_MCUBOOT_PAD_SIZE) +#endif + +#ifdef CONFIG_MCUBOOT + /* lib is part of MCUboot -> operate on the primary application slot */ + #define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_PRIMARY_ID +#else + /* lib is part of the App -> operate on active slot */ +#if (PM_ADDRESS - PM_ADDRESS_OFFSET) == PM_MCUBOOT_PRIMARY_ADDRESS + #define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_PRIMARY_ID +#elif (PM_ADDRESS - PM_ADDRESS_OFFSET) == PM_MCUBOOT_SECONDARY_ADDRESS + #define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_SECONDARY_ID +#else + #error Missing partition definitions. +#endif +#endif /* CONFIG_MCUBOOT */ +#endif /* CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER != -1 */ + +#else + +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) /* For RAM LOAD mode, the active image must be fetched from the bootloader */ #define ACTIVE_SLOT_FLASH_AREA_ID boot_fetch_active_slot() #define INVALID_SLOT_ID 255 @@ -68,6 +109,8 @@ enum IMAGE_INDEXES { #define ACTIVE_SLOT_FLASH_AREA_ID DT_FIXED_PARTITION_ID(DT_CHOSEN(zephyr_code_partition)) #endif +#endif /* USE_PARTITION_MANAGER */ + /* * Raw (on-flash) representation of the v1 image header. */ diff --git a/subsys/dfu/boot/mcuboot_shell.c b/subsys/dfu/boot/mcuboot_shell.c index be4e558713f1..e167bc1e39b8 100644 --- a/subsys/dfu/boot/mcuboot_shell.c +++ b/subsys/dfu/boot/mcuboot_shell.c @@ -20,6 +20,16 @@ #endif #endif +#if USE_PARTITION_MANAGER +#include + +#ifdef CONFIG_NCS_IS_VARIANT_IMAGE +#define ACTIVE_IMAGE_ID PM_MCUBOOT_SECONDARY_ID +#else +#define ACTIVE_IMAGE_ID PM_MCUBOOT_PRIMARY_ID +#endif +#endif + struct area_desc { const char *name; unsigned int id; @@ -93,6 +103,35 @@ static int cmd_mcuboot_erase(const struct shell *sh, size_t argc, id = strtoul(argv[1], NULL, 0); /* Check if this is the parent (MCUboot) or own slot and if so, deny the request */ +#if USE_PARTITION_MANAGER +#ifdef PM_MCUBOOT_ID + if (id == PM_MCUBOOT_ID || id == PM_MCUBOOT_PAD_ID) { + shell_error(sh, "Cannot erase boot partition"); + return -EACCES; + } +#endif + +#ifdef PM_APP_ID + if (id == PM_APP_ID) { + shell_error(sh, "Cannot erase this area"); + return -EACCES; + } +#endif + +#ifdef PM_MCUBOOT_PRIMARY_APP_ID + if (id == PM_MCUBOOT_PRIMARY_APP_ID) { + shell_error(sh, "Cannot erase this area"); + return -EACCES; + } +#endif + +#ifdef ACTIVE_IMAGE_ID + if (id == ACTIVE_IMAGE_ID) { + shell_error(sh, "Cannot erase active partitions"); + return -EACCES; + } +#endif +#else #if FIXED_PARTITION_EXISTS(boot_partition) if (id == FIXED_PARTITION_ID(boot_partition)) { shell_error(sh, "Cannot erase boot partition"); @@ -105,6 +144,7 @@ static int cmd_mcuboot_erase(const struct shell *sh, size_t argc, shell_error(sh, "Cannot erase active partitions"); return -EACCES; } +#endif #endif err = boot_erase_img_bank(id); diff --git a/subsys/dfu/img_util/flash_img.c b/subsys/dfu/img_util/flash_img.c index 83eb013c6612..24e95a8dc1a9 100644 --- a/subsys/dfu/img_util/flash_img.c +++ b/subsys/dfu/img_util/flash_img.c @@ -23,8 +23,9 @@ LOG_MODULE_REGISTER(flash_img, CONFIG_IMG_MANAGER_LOG_LEVEL); #include #endif -#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ - (FIXED_PARTITION_OFFSET(label) == CONFIG_FLASH_LOAD_OFFSET) +#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ + (FIXED_PARTITION_OFFSET(label) <= CONFIG_FLASH_LOAD_OFFSET && \ + FIXED_PARTITION_OFFSET(label) + FIXED_PARTITION_SIZE(label) > CONFIG_FLASH_LOAD_OFFSET) #include #if defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) && (CONFIG_TFM_MCUBOOT_IMAGE_NUMBER == 2) diff --git a/subsys/fs/littlefs_fs.c b/subsys/fs/littlefs_fs.c index 7cf8aaa44c7b..5abbf95f949e 100644 --- a/subsys/fs/littlefs_fs.c +++ b/subsys/fs/littlefs_fs.c @@ -1103,7 +1103,12 @@ struct fs_mount_t FS_FSTAB_ENTRY(DT_DRV_INST(inst)) = { \ .type = FS_LITTLEFS, \ .mnt_point = DT_INST_PROP(inst, mount_point), \ .fs_data = &fs_data_##inst, \ - .storage_dev = (void *)DT_FIXED_PARTITION_ID(FS_PARTITION(inst)), \ + .storage_dev = (void *) \ + COND_CODE_1(USE_PARTITION_MANAGER, \ + (COND_CODE_1(FIXED_PARTITION_EXISTS(littlefs_storage), \ + (FIXED_PARTITION_ID(littlefs_storage)), \ + (FIXED_PARTITION_ID(storage)))), \ + (DT_FIXED_PARTITION_ID(FS_PARTITION(inst)))), \ .flags = FSTAB_ENTRY_DT_MOUNT_FLAGS(DT_DRV_INST(inst)), \ }; diff --git a/subsys/fs/nvs/Kconfig b/subsys/fs/nvs/Kconfig index 48915c2f048e..21798932f521 100644 --- a/subsys/fs/nvs/Kconfig +++ b/subsys/fs/nvs/Kconfig @@ -29,6 +29,15 @@ config NVS_LOOKUP_CACHE_SIZE Number of entries in Non-volatile Storage lookup cache. It is recommended that it be a power of 2. +config NVS_LOOKUP_CACHE_FOR_SETTINGS + bool "Non-volatile Storage lookup cache optimized for settings" + depends on NVS_LOOKUP_CACHE + help + Use the lookup cache hash function that results in the least number of + collissions and, in turn, the best NVS performance provided that the NVS + is used as the settings backend only. This option should NOT be enabled + if the NVS is also written to directly, outside the settings layer. + config NVS_DATA_CRC bool "Non-volatile Storage CRC protection on the data" help diff --git a/subsys/fs/nvs/nvs.c b/subsys/fs/nvs/nvs.c index 8a710d570fb1..f36d5b76dd56 100644 --- a/subsys/fs/nvs/nvs.c +++ b/subsys/fs/nvs/nvs.c @@ -13,6 +13,11 @@ #include #include "nvs_priv.h" +#ifdef CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS +#include +#include +#endif + #include LOG_MODULE_REGISTER(fs_nvs, CONFIG_NVS_LOG_LEVEL); @@ -21,6 +26,45 @@ static int nvs_ate_valid(struct nvs_fs *fs, const struct nvs_ate *entry); #ifdef CONFIG_NVS_LOOKUP_CACHE +#ifdef CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS + +static inline size_t nvs_lookup_cache_pos(uint16_t id) +{ + /* + * 1. The NVS settings backend uses up to (NVS_NAME_ID_OFFSET - 1) NVS IDs to + store keys and equal number of NVS IDs to store values. + * 2. For each key-value pair, the value is stored at NVS ID greater by exactly + * NVS_NAME_ID_OFFSET than NVS ID that holds the key. + * 3. The backend tries to minimize the range of NVS IDs used to store keys. + * That is, NVS IDs are allocated sequentially, and freed NVS IDs are reused + * before allocating new ones. + * + * Therefore, to assure the least number of collisions in the lookup cache, + * the least significant bit of the hash indicates whether the given NVS ID + * represents a key or a value, and remaining bits of the hash are set to + * the ordinal number of the key-value pair. Consequently, the hash function + * provides the following mapping: + * + * 1st settings key => hash 0 + * 1st settings value => hash 1 + * 2nd settings key => hash 2 + * 2nd settings value => hash 3 + * ... + */ + BUILD_ASSERT(IS_POWER_OF_TWO(NVS_NAMECNT_ID), "NVS_NAMECNT_ID is not power of 2"); + BUILD_ASSERT(IS_POWER_OF_TWO(NVS_NAME_ID_OFFSET), "NVS_NAME_ID_OFFSET is not power of 2"); + + uint16_t key_value_bit; + uint16_t key_value_ord; + + key_value_bit = (id >> LOG2(NVS_NAME_ID_OFFSET)) & 1; + key_value_ord = id & (NVS_NAME_ID_OFFSET - 1); + + return ((key_value_ord << 1) | key_value_bit) % CONFIG_NVS_LOOKUP_CACHE_SIZE; +} + +#else /* CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS */ + static inline size_t nvs_lookup_cache_pos(uint16_t id) { uint16_t hash; @@ -36,6 +80,8 @@ static inline size_t nvs_lookup_cache_pos(uint16_t id) return hash % CONFIG_NVS_LOOKUP_CACHE_SIZE; } +#endif /* CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS */ + static int nvs_lookup_cache_rebuild(struct nvs_fs *fs) { int rc; diff --git a/subsys/fs/zms/Kconfig b/subsys/fs/zms/Kconfig index 9266fada236a..f20310a87620 100644 --- a/subsys/fs/zms/Kconfig +++ b/subsys/fs/zms/Kconfig @@ -16,6 +16,15 @@ config ZMS if ZMS +config ZMS_ID_64BIT + bool "64 bit ZMS IDs" + help + When this option is true, the `zms_id_t` values passed to ZMS APIs will be 64 bit, + as opposed to the default 32 bit. + This option will also change the format of allocation table entries (ATEs) in memory + to accommodate larger IDs. Currently, this will make ZMS unable to mount an existing + file system if it has been initialized with a different ATE format. + config ZMS_LOOKUP_CACHE bool "ZMS lookup cache" help @@ -34,6 +43,7 @@ config ZMS_LOOKUP_CACHE_SIZE config ZMS_DATA_CRC bool "ZMS data CRC" + depends on !ZMS_ID_64BIT config ZMS_CUSTOMIZE_BLOCK_SIZE bool "Customize the size of the buffer used internally for reads and writes" @@ -54,6 +64,7 @@ config ZMS_CUSTOM_BLOCK_SIZE config ZMS_LOOKUP_CACHE_FOR_SETTINGS bool "ZMS Storage lookup cache optimized for settings" depends on ZMS_LOOKUP_CACHE && SETTINGS_ZMS + depends on !ZMS_ID_64BIT help Enable usage of lookup cache based on hashes to get, the best ZMS performance, provided that the ZMS is used only for the purpose of providing the settings diff --git a/subsys/fs/zms/zms.c b/subsys/fs/zms/zms.c index b4b11aa6923e..babf6d09b60f 100644 --- a/subsys/fs/zms/zms.c +++ b/subsys/fs/zms/zms.c @@ -13,8 +13,12 @@ #include #include "zms_priv.h" #ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS +#ifdef CONFIG_SETTINGS_ZMS_LEGACY +#include +#else #include #endif +#endif #include LOG_MODULE_REGISTER(fs_zms, CONFIG_ZMS_LOG_LEVEL); @@ -29,11 +33,43 @@ static int zms_ate_valid_different_sector(struct zms_fs *fs, const struct zms_at #ifdef CONFIG_ZMS_LOOKUP_CACHE -static inline size_t zms_lookup_cache_pos(uint32_t id) +static inline size_t zms_lookup_cache_pos(zms_id_t id) { - uint32_t hash = id; - #ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS +#ifdef CONFIG_SETTINGS_ZMS_LEGACY + /* + * 1. The ZMS settings backend uses up to (ZMS_NAME_ID_OFFSET - 1) ZMS IDs to + store keys and equal number of ZMS IDs to store values. + * 2. For each key-value pair, the value is stored at ZMS ID greater by exactly + * ZMS_NAME_ID_OFFSET than ZMS ID that holds the key. + * 3. The backend tries to minimize the range of ZMS IDs used to store keys. + * That is, ZMS IDs are allocated sequentially, and freed ZMS IDs are reused + * before allocating new ones. + * + * Therefore, to assure the least number of collisions in the lookup cache, + * the least significant bit of the hash indicates whether the given ZMS ID + * represents a key or a value, and remaining bits of the hash are set to + * the ordinal number of the key-value pair. Consequently, the hash function + * provides the following mapping: + * + * 1st settings key => hash 0 + * 1st settings value => hash 1 + * 2nd settings key => hash 2 + * 2nd settings value => hash 3 + * ... + */ + BUILD_ASSERT(IS_POWER_OF_TWO(ZMS_NAMECNT_ID), "ZMS_NAMECNT_ID is not power of 2"); + BUILD_ASSERT(IS_POWER_OF_TWO(ZMS_NAME_ID_OFFSET), "ZMS_NAME_ID_OFFSET is not power of 2"); + + uint32_t key_value_bit; + uint32_t key_value_ord; + uint32_t hash; + + key_value_bit = (id >> LOG2(ZMS_NAME_ID_OFFSET)) & 1; + key_value_ord = id & (ZMS_NAME_ID_OFFSET - 1); + + hash = ((key_value_ord << 1) | key_value_bit); +#else /* * 1. Settings subsystem is storing the name ID and the linked list node ID * with only one bit difference at BIT(0). @@ -52,14 +88,28 @@ static inline size_t zms_lookup_cache_pos(uint32_t id) uint32_t key_value_bit; uint32_t key_value_hash; uint32_t key_value_ll; + uint32_t hash; key_value_bit = (id >> LOG2(ZMS_DATA_ID_OFFSET)) & 1; key_value_hash = (id & ZMS_HASH_MASK) >> (CONFIG_SETTINGS_ZMS_MAX_COLLISIONS_BITS + 1); key_value_ll = id & BIT(0); hash = (key_value_hash << 2) | (key_value_bit << 1) | key_value_ll; +#endif /* CONFIG_SETTINGS_ZMS_LEGACY */ + +#elif defined(CONFIG_ZMS_ID_64BIT) + /* 64-bit integer hash function found by https://github.com/skeeto/hash-prospector. */ + uint64_t hash = id; + + hash ^= hash >> 32; + hash *= 0x42ab4abe4c475039ULL; + hash ^= hash >> 31; + hash *= 0xfa90c4424c537791ULL; + hash ^= hash >> 32; #else /* 32-bit integer hash function found by https://github.com/skeeto/hash-prospector. */ + uint32_t hash = id; + hash ^= hash >> 16; hash *= 0x7feb352dU; hash ^= hash >> 15; @@ -239,7 +289,7 @@ static int zms_flash_ate_wrt(struct zms_fs *fs, const struct zms_ate *entry) goto end; } #ifdef CONFIG_ZMS_LOOKUP_CACHE - /* 0xFFFFFFFF is a special-purpose identifier. Exclude it from the cache */ + /* ZMS_HEAD_ID is a special-purpose identifier. Exclude it from the cache */ if (entry->id != ZMS_HEAD_ID) { fs->lookup_cache[zms_lookup_cache_pos(entry->id)] = fs->ate_wra; } @@ -487,7 +537,7 @@ static bool zms_close_ate_valid(struct zms_fs *fs, const struct zms_ate *entry) /* zms_empty_ate_valid validates an sector empty ate. * A valid sector empty ate should be: * - a valid ate - * - with len = 0xffff and id = 0xffffffff + * - with len = 0xffff and id = ZMS_HEAD_ID * return true if valid, false otherwise */ static bool zms_empty_ate_valid(struct zms_fs *fs, const struct zms_ate *entry) @@ -500,7 +550,7 @@ static bool zms_empty_ate_valid(struct zms_fs *fs, const struct zms_ate *entry) * Valid gc_done_ate: * - valid ate * - len = 0 - * - id = 0xffffffff + * - id = ZMS_HEAD_ID * return true if valid, false otherwise */ static bool zms_gc_done_ate_valid(struct zms_fs *fs, const struct zms_ate *entry) @@ -509,6 +559,18 @@ static bool zms_gc_done_ate_valid(struct zms_fs *fs, const struct zms_ate *entry (entry->id == ZMS_HEAD_ID)); } +/* zms_sector_closed checks whether the current sector is closed, which would imply + * that the empty ATE and close ATE are both valid and have matching cycle counters + * + * return true if closed, false otherwise + */ +static bool zms_sector_closed(struct zms_fs *fs, struct zms_ate *empty_ate, + struct zms_ate *close_ate) +{ + return (zms_empty_ate_valid(fs, empty_ate) && zms_close_ate_valid(fs, close_ate) && + (empty_ate->cycle_cnt == close_ate->cycle_cnt)); +} + /* Read empty and close ATE of the sector where belongs address "addr" and * validates that the sector is closed. * retval: 0 if sector is not close @@ -526,8 +588,7 @@ static int zms_validate_closed_sector(struct zms_fs *fs, uint64_t addr, struct z return rc; } - if (zms_empty_ate_valid(fs, empty_ate) && zms_close_ate_valid(fs, close_ate) && - (empty_ate->cycle_cnt == close_ate->cycle_cnt)) { + if (zms_sector_closed(fs, empty_ate, close_ate)) { /* Closed sector validated */ return 1; } @@ -536,7 +597,7 @@ static int zms_validate_closed_sector(struct zms_fs *fs, uint64_t addr, struct z } /* store an entry in flash */ -static int zms_flash_write_entry(struct zms_fs *fs, uint32_t id, const void *data, size_t len) +static int zms_flash_write_entry(struct zms_fs *fs, zms_id_t id, const void *data, size_t len) { int rc; struct zms_ate entry; @@ -549,13 +610,13 @@ static int zms_flash_write_entry(struct zms_fs *fs, uint32_t id, const void *dat entry.cycle_cnt = fs->sector_cycle; if (len > ZMS_DATA_IN_ATE_SIZE) { - /* only compute CRC if len is greater than 8 bytes */ - if (IS_ENABLED(CONFIG_ZMS_DATA_CRC)) { - entry.data_crc = crc32_ieee(data, len); - } +#ifdef CONFIG_ZMS_DATA_CRC + /* only compute CRC if data is to be stored outside of entry */ + entry.data_crc = crc32_ieee(data, len); +#endif entry.offset = (uint32_t)SECTOR_OFFSET(fs->data_wra); } else if ((len > 0) && (len <= ZMS_DATA_IN_ATE_SIZE)) { - /* Copy data into entry for small data ( < 8B) */ + /* Copy data into entry for small data (at most ZMS_DATA_IN_ATE_SIZE bytes) */ memcpy(&entry.data, data, len); } @@ -688,10 +749,12 @@ static int zms_sector_close(struct zms_fs *fs) struct zms_ate close_ate; struct zms_ate garbage_ate; + /* Initialize all members to 0xff */ + memset(&close_ate, 0xff, sizeof(struct zms_ate)); + close_ate.id = ZMS_HEAD_ID; close_ate.len = 0U; close_ate.offset = (uint32_t)SECTOR_OFFSET(fs->ate_wra + fs->ate_size); - close_ate.metadata = 0xffffffff; close_ate.cycle_cnt = fs->sector_cycle; /* When we close the sector, we must write all non used ATE with @@ -740,11 +803,13 @@ static int zms_add_gc_done_ate(struct zms_fs *fs) { struct zms_ate gc_done_ate; + /* Initialize all members to 0xff */ + memset(&gc_done_ate, 0xff, sizeof(struct zms_ate)); + LOG_DBG("Adding gc done ate at %llx", fs->ate_wra); gc_done_ate.id = ZMS_HEAD_ID; gc_done_ate.len = 0U; gc_done_ate.offset = (uint32_t)SECTOR_OFFSET(fs->data_wra); - gc_done_ate.metadata = 0xffffffff; gc_done_ate.cycle_cnt = fs->sector_cycle; zms_ate_crc8_update(&gc_done_ate); @@ -793,14 +858,17 @@ static int zms_add_empty_ate(struct zms_fs *fs, uint64_t addr) int rc = 0; uint64_t previous_ate_wra; + /* Initialize all members to 0 */ + memset(&empty_ate, 0, sizeof(struct zms_ate)); + addr &= ADDR_SECT_MASK; LOG_DBG("Adding empty ate at %llx", (uint64_t)(addr + fs->sector_size - fs->ate_size)); empty_ate.id = ZMS_HEAD_ID; empty_ate.len = 0xffff; - empty_ate.offset = 0U; - empty_ate.metadata = - FIELD_PREP(ZMS_MAGIC_NUMBER_MASK, ZMS_MAGIC_NUMBER) | ZMS_DEFAULT_VERSION; + empty_ate.metadata = FIELD_PREP(ZMS_VERSION_MASK, ZMS_DEFAULT_VERSION) | + FIELD_PREP(ZMS_MAGIC_NUMBER_MASK, ZMS_MAGIC_NUMBER) | + FIELD_PREP(ZMS_ATE_FORMAT_MASK, ZMS_DEFAULT_ATE_FORMAT); rc = zms_get_sector_cycle(fs, addr, &cycle_cnt); if (rc == -ENOENT) { @@ -893,7 +961,7 @@ static int zms_get_sector_header(struct zms_fs *fs, uint64_t addr, struct zms_at * @retval 1 valid ATE with same ID found * @retval < 0 An error happened */ -static int zms_find_ate_with_id(struct zms_fs *fs, uint32_t id, uint64_t start_addr, +static int zms_find_ate_with_id(struct zms_fs *fs, zms_id_t id, uint64_t start_addr, uint64_t end_addr, struct zms_ate *ate, uint64_t *ate_addr) { int rc; @@ -1044,10 +1112,10 @@ static int zms_gc(struct zms_fs *fs) */ if (wlk_prev_addr == gc_prev_addr) { /* copy needed */ - LOG_DBG("Moving %d, len %d", gc_ate.id, gc_ate.len); + LOG_DBG("Moving %lld, len %d", (long long)gc_ate.id, gc_ate.len); if (gc_ate.len > ZMS_DATA_IN_ATE_SIZE) { - /* Copy Data only when len > 8 + /* Copy Data only when len > ZMS_DATA_IN_ATE_SIZE * Otherwise, Data is already inside ATE */ data_addr = (gc_prev_addr & ADDR_SECT_MASK); @@ -1156,16 +1224,28 @@ static int zms_init(struct zms_fs *fs) for (i = 0; i < fs->sector_count; i++) { addr = zms_close_ate_addr(fs, ((uint64_t)i << ADDR_SECT_SHIFT)); - /* verify if the sector is closed */ - sec_closed = zms_validate_closed_sector(fs, addr, &empty_ate, &close_ate); - if (sec_closed < 0) { - rc = sec_closed; + /* read the header ATEs */ + rc = zms_get_sector_header(fs, addr, &empty_ate, &close_ate); + if (rc) { goto end; } /* update cycle count */ fs->sector_cycle = empty_ate.cycle_cnt; - if (sec_closed == 1) { + /* Check the ATE format indicator so that we know how to validate ATEs. + * The metadata field has the same offset and size in all ATE formats + * (the same is guaranteed for crc8 and cycle_cnt). + * Currently, ZMS can only recognize one of its supported ATE formats + * (the one chosen at build time), so their indicators are defined for + * the possibility of a future extension. + * If this indicator is unknown, then consider the header ATEs invalid, + * because we might not be dealing with ZMS contents at all. + */ + if (ZMS_GET_ATE_FORMAT(empty_ate.metadata) != ZMS_DEFAULT_ATE_FORMAT) { + continue; + } + + if (zms_sector_closed(fs, &empty_ate, &close_ate)) { /* closed sector */ closed_sectors++; /* Let's verify that this is a ZMS storage system */ @@ -1223,7 +1303,8 @@ static int zms_init(struct zms_fs *fs) goto end; } - if (zms_empty_ate_valid(fs, &empty_ate)) { + if ((ZMS_GET_ATE_FORMAT(empty_ate.metadata) == ZMS_DEFAULT_ATE_FORMAT) && + zms_empty_ate_valid(fs, &empty_ate)) { /* Empty ATE is valid, let's verify that this is a ZMS storage system */ if (ZMS_GET_MAGIC_NUMBER(empty_ate.metadata) == ZMS_MAGIC_NUMBER) { zms_magic_exist = true; @@ -1468,7 +1549,7 @@ int zms_mount(struct zms_fs *fs) return 0; } -ssize_t zms_write(struct zms_fs *fs, uint32_t id, const void *data, size_t len) +ssize_t zms_write(struct zms_fs *fs, zms_id_t id, const void *data, size_t len) { int rc; size_t data_size; @@ -1613,12 +1694,12 @@ ssize_t zms_write(struct zms_fs *fs, uint32_t id, const void *data, size_t len) return rc; } -int zms_delete(struct zms_fs *fs, uint32_t id) +int zms_delete(struct zms_fs *fs, zms_id_t id) { return zms_write(fs, id, NULL, 0); } -ssize_t zms_read_hist(struct zms_fs *fs, uint32_t id, void *data, size_t len, uint32_t cnt) +ssize_t zms_read_hist(struct zms_fs *fs, zms_id_t id, void *data, size_t len, uint32_t cnt) { int rc; int prev_found = 0; @@ -1719,7 +1800,7 @@ ssize_t zms_read_hist(struct zms_fs *fs, uint32_t id, void *data, size_t len, ui return rc; } -ssize_t zms_read(struct zms_fs *fs, uint32_t id, void *data, size_t len) +ssize_t zms_read(struct zms_fs *fs, zms_id_t id, void *data, size_t len) { int rc; @@ -1732,7 +1813,7 @@ ssize_t zms_read(struct zms_fs *fs, uint32_t id, void *data, size_t len) return MIN(rc, len); } -ssize_t zms_get_data_length(struct zms_fs *fs, uint32_t id) +ssize_t zms_get_data_length(struct zms_fs *fs, zms_id_t id) { int rc; diff --git a/subsys/fs/zms/zms_priv.h b/subsys/fs/zms/zms_priv.h index 84f77296f4f3..44cfb2f3d280 100644 --- a/subsys/fs/zms/zms_priv.h +++ b/subsys/fs/zms/zms_priv.h @@ -28,7 +28,6 @@ #endif #define ZMS_LOOKUP_CACHE_NO_ADDR GENMASK64(63, 0) -#define ZMS_HEAD_ID GENMASK(31, 0) #define ZMS_VERSION_MASK GENMASK(7, 0) #define ZMS_GET_VERSION(x) FIELD_GET(ZMS_VERSION_MASK, x) @@ -36,14 +35,28 @@ #define ZMS_MAGIC_NUMBER 0x42 /* murmur3a hash of "ZMS" (MSB) */ #define ZMS_MAGIC_NUMBER_MASK GENMASK(15, 8) #define ZMS_GET_MAGIC_NUMBER(x) FIELD_GET(ZMS_MAGIC_NUMBER_MASK, x) +#define ZMS_ATE_FORMAT_MASK GENMASK(19, 16) +#define ZMS_GET_ATE_FORMAT(x) FIELD_GET(ZMS_ATE_FORMAT_MASK, x) #define ZMS_MIN_ATE_NUM 5 #define ZMS_INVALID_SECTOR_NUM -1 -#define ZMS_DATA_IN_ATE_SIZE 8 + +#define ZMS_ATE_FORMAT_ID_32BIT 0 +#define ZMS_ATE_FORMAT_ID_64BIT 1 + +#if !defined(CONFIG_ZMS_ID_64BIT) +#define ZMS_DEFAULT_ATE_FORMAT ZMS_ATE_FORMAT_ID_32BIT +#define ZMS_HEAD_ID GENMASK(31, 0) +#else +#define ZMS_DEFAULT_ATE_FORMAT ZMS_ATE_FORMAT_ID_64BIT +#define ZMS_HEAD_ID GENMASK64(63, 0) +#endif /* CONFIG_ZMS_ID_64BIT */ /** * @ingroup zms_data_structures * ZMS Allocation Table Entry (ATE) structure + * + * @note This structure depends on @kconfig{CONFIG_ZMS_ID_64BIT}. */ struct zms_ate { /** crc8 check of the entry */ @@ -52,6 +65,8 @@ struct zms_ate { uint8_t cycle_cnt; /** data len within sector */ uint16_t len; + +#if ZMS_DEFAULT_ATE_FORMAT == ZMS_ATE_FORMAT_ID_32BIT /** data id */ uint32_t id; union { @@ -75,6 +90,22 @@ struct zms_ate { }; }; }; + +#elif ZMS_DEFAULT_ATE_FORMAT == ZMS_ATE_FORMAT_ID_64BIT + /** data id */ + uint64_t id; + union { + /** data field used to store small sized data */ + uint8_t data[4]; + /** data offset within sector */ + uint32_t offset; + /** Used to store metadata information such as storage version. */ + uint32_t metadata; + }; +#endif /* ZMS_DEFAULT_ATE_FORMAT */ + } __packed; +#define ZMS_DATA_IN_ATE_SIZE SIZEOF_FIELD(struct zms_ate, data) + #endif /* __ZMS_PRIV_H_ */ diff --git a/subsys/ipc/ipc_service/lib/Kconfig.icmsg b/subsys/ipc/ipc_service/lib/Kconfig.icmsg index 6bbc79d4fa2a..fa84c399ffb5 100644 --- a/subsys/ipc/ipc_service/lib/Kconfig.icmsg +++ b/subsys/ipc/ipc_service/lib/Kconfig.icmsg @@ -43,6 +43,7 @@ if IPC_SERVICE_BACKEND_ICMSG_WQ_ENABLE config IPC_SERVICE_BACKEND_ICMSG_WQ_STACK_SIZE int "Size of RX work queue stack" + default 5400 if NRF71_ON_IPC default 1280 help Size of stack used by work queue RX thread. This work queue is diff --git a/subsys/ipc/rpmsg_service/rpmsg_backend.h b/subsys/ipc/rpmsg_service/rpmsg_backend.h index a74e46b85207..9996e1d74d9b 100644 --- a/subsys/ipc/rpmsg_service/rpmsg_backend.h +++ b/subsys/ipc/rpmsg_service/rpmsg_backend.h @@ -13,8 +13,35 @@ extern "C" { #endif +#if CONFIG_PARTITION_MANAGER_ENABLED + +#include "pm_config.h" + +#if defined(PM_RPMSG_NRF53_SRAM_ADDRESS) || defined(PM__RPMSG_NRF53_SRAM_ADDRESS) + +#if defined(PM_RPMSG_NRF53_SRAM_ADDRESS) +#define VDEV_START_ADDR PM_RPMSG_NRF53_SRAM_ADDRESS +#define VDEV_SIZE PM_RPMSG_NRF53_SRAM_SIZE +#else +/* The current image is a child image in a different domain than the image + * which defined the required values. To reach the values of the parent domain + * we use the 'PM__' variant of the define. + */ +#define VDEV_START_ADDR PM__RPMSG_NRF53_SRAM_ADDRESS +#define VDEV_SIZE PM__RPMSG_NRF53_SRAM_SIZE +#endif /* defined(PM_RPMSG_NRF53_SRAM_ADDRESS) */ + +#else #define VDEV_START_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ipc_shm)) #define VDEV_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ipc_shm)) +#endif /* defined(PM_RPMSG_NRF53_SRAM_ADDRESS) || defined(PM__RPMSG_NRF53_SRAM_ADDRESS) */ + +#else + +#define VDEV_START_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ipc_shm)) +#define VDEV_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ipc_shm)) + +#endif /* CONFIG_PARTITION_MANAGER_ENABLED */ #define VDEV_STATUS_ADDR VDEV_START_ADDR #define VDEV_STATUS_SIZE 0x400 diff --git a/subsys/jwt/Kconfig b/subsys/jwt/Kconfig index 052908a77754..c1cafcc829cf 100644 --- a/subsys/jwt/Kconfig +++ b/subsys/jwt/Kconfig @@ -28,8 +28,7 @@ config JWT_SIGN_RSA_LEGACY config JWT_SIGN_RSA_PSA bool "Use RSA signature (RS-256). Use PSA Crypto API." - select MBEDTLS if !BUILD_WITH_TFM - select MBEDTLS_PSA_CRYPTO_C if !BUILD_WITH_TFM + select PSA_CRYPTO select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT select PSA_WANT_ALG_RSA_PKCS1V15_SIGN @@ -37,8 +36,7 @@ config JWT_SIGN_RSA_PSA config JWT_SIGN_ECDSA_PSA bool "Use ECDSA signature (ES-256). Use PSA Crypto API." - select MBEDTLS if !BUILD_WITH_TFM - select MBEDTLS_PSA_CRYPTO_C if !BUILD_WITH_TFM + select PSA_CRYPTO select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT select PSA_WANT_ALG_ECDSA select PSA_WANT_ECC_SECP_R1_256 diff --git a/subsys/logging/frontends/Kconfig b/subsys/logging/frontends/Kconfig index 6e5602763574..8bad85c69814 100644 --- a/subsys/logging/frontends/Kconfig +++ b/subsys/logging/frontends/Kconfig @@ -46,7 +46,7 @@ config LOG_FRONTEND_STMESP_DICT config LOG_FRONTEND_STMESP_FSC bool "Send fully self-contained messages" - select LOG_MSG_APPEND_RO_STRING_LOC if !(NRF_ETR || \ + select LOG_MSG_APPEND_RO_STRING_LOC if !(DEBUG_NRF_ETR || \ SOC_NRF54H20_CPUPPR || SOC_NRF54H20_CPUFLPR) config LOG_FRONTEND_STMESP_FLUSH_COUNT @@ -70,7 +70,7 @@ config LOG_FRONTEND_STMESP_DICT_VER config LOG_FRONTEND_STMESP_TURBO_LOG bool "Optimize short_logs" select LOG_CUSTOM_HEADER - default y if (NRF_ETR || SOC_NRF54H20_CPUPPR || SOC_NRF54H20_CPUFLPR) \ + default y if (DEBUG_NRF_ETR || SOC_NRF54H20_CPUPPR || SOC_NRF54H20_CPUFLPR) \ && LOG_FRONTEND_STMESP_FSC help When enabled, then logging messages with 0 and 1 numeric argument are diff --git a/subsys/logging/frontends/log_frontend_stmesp.c b/subsys/logging/frontends/log_frontend_stmesp.c index 0ede3cb48906..7cdd16ffdd34 100644 --- a/subsys/logging/frontends/log_frontend_stmesp.c +++ b/subsys/logging/frontends/log_frontend_stmesp.c @@ -11,8 +11,8 @@ #include #include #include -#ifdef CONFIG_NRF_ETR -#include +#ifdef CONFIG_DEBUG_NRF_ETR +#include #endif /* Only 32 bit platforms supported. */ @@ -574,15 +574,16 @@ void log_frontend_simple_2(const void *source, uint32_t level, const char *fmt, void log_frontend_panic(void) { in_panic = true; -#ifdef CONFIG_NRF_ETR - nrf_etr_flush(); +#ifdef CONFIG_DEBUG_NRF_ETR + debug_nrf_etr_flush(); #endif } void log_frontend_init(void) { -#if defined(CONFIG_LOG_FRONTEND_STPESP_TURBO_SOURCE_PORT_ID) && !defined(CONFIG_NRF_ETR) && \ - !defined(CONFIG_LOG_MSG_APPEND_RO_STRING_LOC) +#if defined(CONFIG_LOG_FRONTEND_STPESP_TURBO_SOURCE_PORT_ID) \ + && !defined(CONFIG_DEBUG_NRF_ETR) \ + && !defined(CONFIG_LOG_MSG_APPEND_RO_STRING_LOC) /* Send location of section with constant source data. It is used by the * application core to retrieve source names of log messages coming from * coprocessors (FLPR and PPR). diff --git a/subsys/mgmt/mcumgr/CMakeLists.txt b/subsys/mgmt/mcumgr/CMakeLists.txt index 39d4a4ca8ce0..3bb21e16f798 100644 --- a/subsys/mgmt/mcumgr/CMakeLists.txt +++ b/subsys/mgmt/mcumgr/CMakeLists.txt @@ -16,3 +16,12 @@ add_subdirectory(transport) add_subdirectory_ifdef(CONFIG_SMP_CLIENT smp_client) zephyr_library_link_libraries(mgmt_mcumgr) + +if(CONFIG_MCUMGR_GRP_IMG_NRF5340_BOOTUTIL_HOOK) + zephyr_include_directories( + ${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/bootutil/include + ${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/zephyr/include + ) + + zephyr_library_sources(bootutil_hooks/nrf53_hooks.c) +endif() diff --git a/subsys/mgmt/mcumgr/Kconfig b/subsys/mgmt/mcumgr/Kconfig index 49bd17f46691..c45cb7f81d6b 100644 --- a/subsys/mgmt/mcumgr/Kconfig +++ b/subsys/mgmt/mcumgr/Kconfig @@ -6,6 +6,7 @@ menuconfig MCUMGR bool "mcumgr Support" depends on NET_BUF depends on ZCBOR + imply BOOT_IMAGE_ACCESS_HOOKS if SOC_NRF5340_CPUAPP && MCUMGR_GRP_IMG && MCUBOOT_NETWORK_CORE_IMAGE_NUMBER > -1 help This option enables the mcumgr management library. diff --git a/subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c b/subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c new file mode 100644 index 000000000000..b372ce4e4945 --- /dev/null +++ b/subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "bootutil/bootutil_public.h" + +int boot_read_swap_state_primary_slot_hook(int image_index, struct boot_swap_state *state) +{ + if (image_index == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + /* Pretend that primary slot of the network core update image is unpopulated */ + state->magic = BOOT_MAGIC_UNSET; + state->swap_type = BOOT_SWAP_TYPE_NONE; + state->image_num = image_index; + state->copy_done = BOOT_FLAG_UNSET; + state->image_ok = BOOT_FLAG_UNSET; + + /* Prevent bootutil from trying to obtain true info */ + return 0; + } + + return BOOT_HOOK_REGULAR; +} diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig index 0915d70e8706..e64f15abd2e6 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig @@ -117,6 +117,24 @@ config MCUMGR_GRP_IMG_REJECT_DIRECT_XIP_MISMATCHED_SLOT The base address can be set, to an image binary header, with imgtool, using the --rom-fixed command line option. +config MCUMGR_GRP_IMG_ALLOW_CONFIRM_NON_ACTIVE_SLOT + bool "Allow to confirm non-active slots of any image" if !MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY + depends on MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT || \ + MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT || \ + MCUBOOT_BOOTLOADER_MODE_SWAP_SCRATCH || \ + MCUBOOT_BOOTLOADER_MODE_SWAP_USING_MOVE || \ + MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET || \ + MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY + default y + help + Allows to confirm non-active slot of any image. + Normally it should not be allowed to confirm any slots via MCUmgr + commands, to prevent confirming something that is broken and was not + verified to boot correctly. + Option always enabled in the overwrite mode, because the permanent + update, that uses the confirm flag, is the intended way to provide + updates. + config MCUMGR_GRP_IMG_FRUGAL_LIST bool "Omit zero, empty or false values from status list" help @@ -219,6 +237,14 @@ config MCUMGR_GRP_IMG_SLOT_INFO_HOOKS This will enable the slot info function hooks which can be used to add additional information to responses. +config MCUMGR_GRP_IMG_NRF5340_BOOTUTIL_HOOK + bool "nRF5340 network core bootutil hook" + depends on SOC_NRF5340_CPUAPP && BOOT_IMAGE_ACCESS_HOOKS && MCUBOOT_NETWORK_CORE_IMAGE_NUMBER > -1 + default y + help + This option will enable a bootutil hook that populates the network core update image + slot with dummy data to allow for uploading a firmware update to the network core. + module = MCUMGR_GRP_IMG module-str = mcumgr_grp_img source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c index 7abcac8afad5..a2bf006b9474 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c @@ -48,8 +48,9 @@ to be able to figure out application running slot. #endif -#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ - (FIXED_PARTITION_OFFSET(label) == CONFIG_FLASH_LOAD_OFFSET) +#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ + (FIXED_PARTITION_OFFSET(label) <= CONFIG_FLASH_LOAD_OFFSET && \ + FIXED_PARTITION_OFFSET(label) + FIXED_PARTITION_SIZE(label) > CONFIG_FLASH_LOAD_OFFSET) BUILD_ASSERT(sizeof(struct image_header) == IMAGE_HEADER_SIZE, "struct image_header not required size"); diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c index fb15c15b6e9e..0ebb722c2a90 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c @@ -127,21 +127,30 @@ img_mgmt_state_flags(int query_slot) int image = query_slot / 2; /* We support max 2 images for now */ int active_slot = img_mgmt_active_slot(image); - /* In case when MCUboot is configured for DirectXIP slot may only be - * active or pending. Slot is marked pending only when version in that slot - * is higher than version of active slot. + /* In case when MCUboot is configured for FW loader/updater mode, slots + * can be either active or non-active. There is no concept of pending + * or confirmed slots. + * + * In case when MCUboot is configured for DirectXIP slot may only be + * active or pending. + * Slot is marked as pending when: + * - version in that slot is higher than version of active slot. + * - versions are equal but slot number is lower than the active slot. */ if (image == img_mgmt_active_image() && query_slot == active_slot) { flags = IMG_MGMT_STATE_F_ACTIVE; +#ifdef CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP } else { struct image_version sver; struct image_version aver; int rcs = img_mgmt_read_info(query_slot, &sver, NULL, NULL); int rca = img_mgmt_read_info(active_slot, &aver, NULL, NULL); - if (rcs == 0 && rca == 0 && img_mgmt_vercmp(&aver, &sver) < 0) { + if (rcs == 0 && rca == 0 && ((img_mgmt_vercmp(&aver, &sver) < 0) || + ((img_mgmt_vercmp(&aver, &sver) == 0) && (active_slot > query_slot)))) { flags = IMG_MGMT_STATE_F_PENDING | IMG_MGMT_STATE_F_PERMANENT; } +#endif /* CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP */ } return flags; @@ -285,18 +294,37 @@ int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type) if (active_slot_state == DIRECT_XIP_BOOT_ONCE) { lt = NEXT_BOOT_TYPE_TEST; } - } else if (img_mgmt_vercmp(&aver, &over) < 0) { + } else if ((img_mgmt_vercmp(&aver, &over) < 0) || + ((img_mgmt_vercmp(&aver, &over) == 0) && (active_slot > other_slot))) { + /* Check if MCUboot will select the non-active slot during the next boot. + * The logic is as follows: + * - If both slots are valid, a slot with higher version is preferred. + * - If both slots are valid and the versions are equal, a slot with lower number + * is preferred. + */ if (other_slot_state == DIRECT_XIP_BOOT_FOREVER) { return_slot = other_slot; } else if (other_slot_state == DIRECT_XIP_BOOT_ONCE) { lt = NEXT_BOOT_TYPE_TEST; return_slot = other_slot; } + } else { + /* There is neither a preference nor a necessity to boot the other slot. + * The active slot will be used again. + */ } out: #else - if (rcs == 0 && rca == 0 && img_mgmt_vercmp(&aver, &over) < 0) { + if (rcs == 0 && rca == 0 && + ((img_mgmt_vercmp(&aver, &over) < 0) || + ((img_mgmt_vercmp(&aver, &over) == 0) && (active_slot > other_slot)))) { + /* Check if MCUboot will select the non-active slot during the next boot. + * The logic is as follows: + * - If both slots are valid, a slot with higher version is preferred. + * - If both slots are valid and the versions are equal, a slot with lower number + * is preferred. + */ return_slot = other_slot; } #endif /* defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) */ @@ -680,6 +708,17 @@ int img_mgmt_set_next_boot_slot(int slot, bool confirm) } #endif + /* The rules above apply only to the inactive image. + * To effectively prevent confirming something that might not have been + * verified to actually be bootable, a new policy was introduced, + * that applies to both active and inactive images. + */ +#ifndef CONFIG_MCUMGR_GRP_IMG_ALLOW_CONFIRM_NON_ACTIVE_SLOT + if (confirm && slot != active_slot) { + return IMG_MGMT_ERR_IMAGE_CONFIRMATION_DENIED; + } +#endif + /* Setting test to active slot is not allowed. */ if (!confirm && slot == active_slot) { return IMG_MGMT_ERR_IMAGE_SETTING_TEST_TO_ACTIVE_DENIED; @@ -728,8 +767,9 @@ int img_mgmt_set_next_boot_slot(int slot, bool confirm) #else int img_mgmt_set_next_boot_slot(int slot, bool confirm) { + int image = img_mgmt_slot_to_image(slot); + int active_slot = img_mgmt_active_slot(image); int active_image = img_mgmt_active_image(); - int active_slot = img_mgmt_active_slot(active_image); LOG_DBG("(%d, %s)", slot, confirm ? "confirm" : "test"); LOG_DBG("aimg = %d, aslot = %d, slot = %d", @@ -739,6 +779,12 @@ int img_mgmt_set_next_boot_slot(int slot, bool confirm) return IMG_MGMT_ERR_IMAGE_SETTING_TEST_TO_ACTIVE_DENIED; } +#ifndef CONFIG_MCUMGR_GRP_IMG_ALLOW_CONFIRM_NON_ACTIVE_SLOT + if (slot != active_slot && confirm) { + return IMG_MGMT_ERR_IMAGE_CONFIRMATION_DENIED; + } +#endif + return img_mgmt_set_next_boot_slot_common(slot, active_slot, confirm); } #endif diff --git a/subsys/modem/CMakeLists.txt b/subsys/modem/CMakeLists.txt index c374bcab9cff..a1db3ab90361 100644 --- a/subsys/modem/CMakeLists.txt +++ b/subsys/modem/CMakeLists.txt @@ -5,6 +5,7 @@ if(CONFIG_MODEM_MODULES) zephyr_library() +zephyr_library_sources_ifdef(CONFIG_MODEM_DEDICATED_WORKQUEUE modem_workqueue.c) zephyr_library_sources_ifdef(CONFIG_MODEM_CHAT modem_chat.c) zephyr_library_sources_ifdef(CONFIG_MODEM_CMUX modem_cmux.c) zephyr_library_sources_ifdef(CONFIG_MODEM_PIPE modem_pipe.c) diff --git a/subsys/modem/Kconfig b/subsys/modem/Kconfig index b7c3f7ba9014..8b4a411c26f6 100644 --- a/subsys/modem/Kconfig +++ b/subsys/modem/Kconfig @@ -6,6 +6,21 @@ menuconfig MODEM_MODULES if MODEM_MODULES +config MODEM_DEDICATED_WORKQUEUE + bool "Use a dedicated workqueue for modem operations" + +if MODEM_DEDICATED_WORKQUEUE + +config MODEM_DEDICATED_WORKQUEUE_STACK_SIZE + int "Modem dedicated workqueue stack size" + default 1024 + +config MODEM_DEDICATED_WORKQUEUE_PRIORITY + int "Modem dedicated workqueue priority" + default SYSTEM_WORKQUEUE_PRIORITY + +endif # MODEM_DEDICATED_WORKQUEUE + config MODEM_CHAT bool "Modem chat module" select RING_BUFFER @@ -42,19 +57,31 @@ config MODEM_CMUX_MTU Maximum Transmission Unit (MTU) size for the CMUX module. Linux ldattach defaults to 127 bytes, 3GPP TS 27.010 to 31. -config MODEM_CMUX_WORK_BUFFER_SIZE - int "CMUX module work buffer size in bytes" - range 23 1507 - default 134 if MODEM_CMUX_DEFAULT_MTU_127 - default 38 +config MODEM_CMUX_WORK_BUFFER_SIZE_EXTRA + int "CMUX module extra work buffer size in bytes" + default 0 help - Size of the work buffer used by the CMUX module. - Recommended size is MODEM_CMUX_MTU + 7 (CMUX header size). + Extra bytes to add to the work buffers used by the CMUX module. + The default size of these buffers is MODEM_CMUX_MTU + 7 (CMUX header size). + +config MODEM_CMUX_T3_TIMEOUT + int "CMUX T3 timeout in seconds" + range 1 255 + default 10 + help + Response Timer for wake-up procedure(T3). + Time in seconds before the link is considered dead. module = MODEM_CMUX module-str = modem_cmux source "subsys/logging/Kconfig.template.log_config" +config MODEM_CMUX_LOG_FRAMES + bool "Log CMUX frames" + depends on MODEM_CMUX_LOG_LEVEL_DBG + help + Enable logging of CMUX frames. This can produce a lot of log data. + endif config MODEM_PIPE @@ -71,6 +98,7 @@ config MODEM_PPP select MODEM_PIPE select RING_BUFFER select CRC + select PM_DEVICE_RUNTIME_ASYNC if PM_DEVICE_RUNTIME if MODEM_PPP diff --git a/subsys/modem/backends/modem_backend_uart.c b/subsys/modem/backends/modem_backend_uart.c index 82242a76c019..13a35406f182 100644 --- a/subsys/modem/backends/modem_backend_uart.c +++ b/subsys/modem/backends/modem_backend_uart.c @@ -39,6 +39,7 @@ struct modem_pipe *modem_backend_uart_init(struct modem_backend_uart *backend, memset(backend, 0x00, sizeof(*backend)); backend->uart = config->uart; + backend->dtr_gpio = config->dtr_gpio; k_work_init_delayable(&backend->receive_ready_work, modem_backend_uart_receive_ready_handler); k_work_init(&backend->transmit_idle_work, modem_backend_uart_transmit_idle_handler); diff --git a/subsys/modem/backends/modem_backend_uart_async.c b/subsys/modem/backends/modem_backend_uart_async.c index d96f513d6061..0cfcff9e86ed 100644 --- a/subsys/modem/backends/modem_backend_uart_async.c +++ b/subsys/modem/backends/modem_backend_uart_async.c @@ -5,11 +5,14 @@ */ #include "modem_backend_uart_async.h" +#include "../modem_workqueue.h" #include LOG_MODULE_REGISTER(modem_backend_uart_async, CONFIG_MODEM_MODULES_LOG_LEVEL); #include +#include +#include #include enum { @@ -58,7 +61,7 @@ static void modem_backend_uart_async_event_handler(const struct device *dev, case UART_TX_DONE: atomic_clear_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT); - k_work_submit(&backend->transmit_idle_work); + modem_work_submit(&backend->transmit_idle_work); break; case UART_TX_ABORTED: @@ -67,7 +70,7 @@ static void modem_backend_uart_async_event_handler(const struct device *dev, } atomic_clear_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT); - k_work_submit(&backend->transmit_idle_work); + modem_work_submit(&backend->transmit_idle_work); break; @@ -127,7 +130,7 @@ static void modem_backend_uart_async_event_handler(const struct device *dev, } k_spin_unlock(&backend->async.receive_rb_lock, key); - k_work_schedule(&backend->receive_ready_work, K_NO_WAIT); + modem_work_schedule(&backend->receive_ready_work, K_NO_WAIT); break; case UART_RX_DISABLED: @@ -144,7 +147,7 @@ static void modem_backend_uart_async_event_handler(const struct device *dev, } if (modem_backend_uart_async_is_uart_stopped(backend)) { - k_work_submit(&backend->async.common.rx_disabled_work); + modem_work_submit(&backend->async.common.rx_disabled_work); } } @@ -156,6 +159,15 @@ static int modem_backend_uart_async_open(void *data) atomic_clear(&backend->async.common.state); ring_buf_reset(&backend->async.receive_rb); + ret = pm_device_runtime_get(backend->uart); + if (ret < 0) { + LOG_ERR("Failed to power on UART: %d", ret); + return ret; + } + if (backend->dtr_gpio) { + gpio_pin_set_dt(backend->dtr_gpio, 1); + } + atomic_set_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT); atomic_set_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_RECEIVING_BIT); @@ -254,7 +266,7 @@ static int modem_backend_uart_async_receive(void *data, uint8_t *buf, size_t siz k_spin_unlock(&backend->async.receive_rb_lock, key); if (!empty) { - k_work_schedule(&backend->receive_ready_work, K_NO_WAIT); + modem_work_schedule(&backend->receive_ready_work, K_NO_WAIT); } return (int)received; @@ -263,10 +275,20 @@ static int modem_backend_uart_async_receive(void *data, uint8_t *buf, size_t siz static int modem_backend_uart_async_close(void *data) { struct modem_backend_uart *backend = (struct modem_backend_uart *)data; + int ret; atomic_clear_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_OPEN_BIT); uart_tx_abort(backend->uart); uart_rx_disable(backend->uart); + if (backend->dtr_gpio) { + gpio_pin_set_dt(backend->dtr_gpio, 0); + } + ret = pm_device_runtime_put_async(backend->uart, K_NO_WAIT); + if (ret < 0) { + LOG_ERR("Failed to power off UART: %d", ret); + return ret; + } + modem_pipe_notify_closed(&backend->pipe); return 0; } diff --git a/subsys/modem/backends/modem_backend_uart_async_hwfc.c b/subsys/modem/backends/modem_backend_uart_async_hwfc.c index 78855daa4eb3..df69c40b6679 100644 --- a/subsys/modem/backends/modem_backend_uart_async_hwfc.c +++ b/subsys/modem/backends/modem_backend_uart_async_hwfc.c @@ -5,11 +5,14 @@ */ #include "modem_backend_uart_async.h" +#include "../modem_workqueue.h" #include LOG_MODULE_REGISTER(modem_backend_uart_async_hwfc, CONFIG_MODEM_MODULES_LOG_LEVEL); #include +#include +#include #include struct rx_buf_t { @@ -136,7 +139,7 @@ static void modem_backend_uart_async_hwfc_event_handler(const struct device *dev case UART_TX_DONE: atomic_clear_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_TRANSMIT_BIT); - k_work_submit(&backend->transmit_idle_work); + modem_work_submit(&backend->transmit_idle_work); break; case UART_TX_ABORTED: @@ -145,7 +148,7 @@ static void modem_backend_uart_async_hwfc_event_handler(const struct device *dev } atomic_clear_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_TRANSMIT_BIT); - k_work_submit(&backend->transmit_idle_work); + modem_work_submit(&backend->transmit_idle_work); break; @@ -182,7 +185,7 @@ static void modem_backend_uart_async_hwfc_event_handler(const struct device *dev rx_buf_unref(&backend->async, evt->data.rx.buf); break; } - k_work_schedule(&backend->receive_ready_work, K_NO_WAIT); + modem_work_schedule(&backend->receive_ready_work, K_NO_WAIT); } break; @@ -191,7 +194,7 @@ static void modem_backend_uart_async_hwfc_event_handler(const struct device *dev MODEM_BACKEND_UART_ASYNC_STATE_OPEN_BIT)) { if (!atomic_test_and_set_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_RECOVERY_BIT)) { - k_work_schedule(&backend->receive_ready_work, K_NO_WAIT); + modem_work_schedule(&backend->receive_ready_work, K_NO_WAIT); LOG_DBG("RX recovery started"); } } @@ -206,7 +209,7 @@ static void modem_backend_uart_async_hwfc_event_handler(const struct device *dev } if (modem_backend_uart_async_hwfc_is_uart_stopped(backend)) { - k_work_submit(&backend->async.common.rx_disabled_work); + modem_work_submit(&backend->async.common.rx_disabled_work); } } @@ -220,6 +223,15 @@ static int modem_backend_uart_async_hwfc_open(void *data) return -ENOMEM; } + ret = pm_device_runtime_get(backend->uart); + if (ret < 0) { + LOG_ERR("Failed to power on UART: %d", ret); + return ret; + } + if (backend->dtr_gpio) { + gpio_pin_set_dt(backend->dtr_gpio, 1); + } + atomic_clear(&backend->async.common.state); atomic_set_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_OPEN_BIT); @@ -335,7 +347,7 @@ static int modem_backend_uart_async_hwfc_receive(void *data, uint8_t *buf, size_ if (backend->async.rx_event.len != 0 || k_msgq_num_used_get(&backend->async.rx_queue) != 0) { - k_work_schedule(&backend->receive_ready_work, K_NO_WAIT); + modem_work_schedule(&backend->receive_ready_work, K_NO_WAIT); } modem_backend_uart_async_hwfc_rx_recovery(backend); @@ -346,6 +358,7 @@ static int modem_backend_uart_async_hwfc_receive(void *data, uint8_t *buf, size_ static int modem_backend_uart_async_hwfc_close(void *data) { struct modem_backend_uart *backend = (struct modem_backend_uart *)data; + int ret; atomic_clear_bit(&backend->async.common.state, MODEM_BACKEND_UART_ASYNC_STATE_OPEN_BIT); uart_tx_abort(backend->uart); @@ -356,6 +369,16 @@ static int modem_backend_uart_async_hwfc_close(void *data) uart_rx_disable(backend->uart); } + if (backend->dtr_gpio) { + gpio_pin_set_dt(backend->dtr_gpio, 0); + } + ret = pm_device_runtime_put_async(backend->uart, K_NO_WAIT); + if (ret < 0) { + LOG_ERR("Failed to power off UART: %d", ret); + return ret; + } + modem_pipe_notify_closed(&backend->pipe); + return 0; } diff --git a/subsys/modem/backends/modem_backend_uart_isr.c b/subsys/modem/backends/modem_backend_uart_isr.c index a9266cc86657..6c6c27c2db2e 100644 --- a/subsys/modem/backends/modem_backend_uart_isr.c +++ b/subsys/modem/backends/modem_backend_uart_isr.c @@ -5,6 +5,7 @@ */ #include "modem_backend_uart_isr.h" +#include "../modem_workqueue.h" #include LOG_MODULE_REGISTER(modem_backend_uart_isr, CONFIG_MODEM_MODULES_LOG_LEVEL); @@ -54,11 +55,11 @@ static void modem_backend_uart_isr_irq_handler_receive_ready(struct modem_backen * It temporarily disables the UART RX IRQ when swapping buffers * which can cause byte loss at higher baud rates. */ - k_work_schedule(&backend->receive_ready_work, - K_MSEC(CONFIG_MODEM_BACKEND_UART_ISR_RECEIVE_IDLE_TIMEOUT_MS)); + modem_work_schedule(&backend->receive_ready_work, + K_MSEC(CONFIG_MODEM_BACKEND_UART_ISR_RECEIVE_IDLE_TIMEOUT_MS)); } else { /* The buffer is getting full. Run the work item immediately to free up space. */ - k_work_reschedule(&backend->receive_ready_work, K_NO_WAIT); + modem_work_reschedule(&backend->receive_ready_work, K_NO_WAIT); } } @@ -70,7 +71,7 @@ static void modem_backend_uart_isr_irq_handler_transmit_ready(struct modem_backe if (ring_buf_is_empty(&backend->isr.transmit_rb) == true) { uart_irq_tx_disable(backend->uart); - k_work_submit(&backend->transmit_idle_work); + modem_work_submit(&backend->transmit_idle_work); return; } diff --git a/subsys/modem/modem_chat.c b/subsys/modem/modem_chat.c index 088a2bc038dc..001be1c7e707 100644 --- a/subsys/modem/modem_chat.c +++ b/subsys/modem/modem_chat.c @@ -15,6 +15,8 @@ LOG_MODULE_REGISTER(modem_chat, CONFIG_MODEM_MODULES_LOG_LEVEL); #include +#include "modem_workqueue.h" + const struct modem_chat_match modem_chat_any_match = MODEM_CHAT_MATCH("", "", NULL); const struct modem_chat_match modem_chat_empty_matches[0]; const struct modem_chat_script_chat modem_chat_empty_script_chats[0]; @@ -127,7 +129,7 @@ static void modem_chat_set_script_send_state(struct modem_chat *chat, static void modem_chat_script_send(struct modem_chat *chat) { modem_chat_set_script_send_state(chat, MODEM_CHAT_SCRIPT_SEND_STATE_REQUEST); - k_work_submit(&chat->script_send_work); + modem_work_submit(&chat->script_send_work); } static void modem_chat_script_set_response_matches(struct modem_chat *chat) @@ -178,7 +180,7 @@ static void modem_chat_script_chat_schedule_send_timeout(struct modem_chat *chat { uint16_t timeout = modem_chat_script_chat_get_send_timeout(chat); - k_work_schedule(&chat->script_send_timeout_work, K_MSEC(timeout)); + modem_work_schedule(&chat->script_send_timeout_work, K_MSEC(timeout)); } static void modem_chat_script_next(struct modem_chat *chat, bool initial) @@ -233,7 +235,7 @@ static void modem_chat_script_start(struct modem_chat *chat, const struct modem_ /* Start timeout work if script started */ if (chat->script != NULL) { - k_work_schedule(&chat->script_timeout_work, K_SECONDS(chat->script->timeout)); + modem_work_schedule(&chat->script_timeout_work, K_SECONDS(chat->script->timeout)); } } @@ -742,7 +744,7 @@ static void modem_chat_process_handler(struct k_work *item) /* Process data */ modem_chat_process_bytes(chat); - k_work_submit(&chat->receive_work); + modem_work_submit(&chat->receive_work); } static void modem_chat_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_event event, @@ -752,11 +754,11 @@ static void modem_chat_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_ev switch (event) { case MODEM_PIPE_EVENT_RECEIVE_READY: - k_work_submit(&chat->receive_work); + modem_work_submit(&chat->receive_work); break; case MODEM_PIPE_EVENT_TRANSMIT_IDLE: - k_work_submit(&chat->script_send_work); + modem_work_submit(&chat->script_send_work); break; default: @@ -880,7 +882,7 @@ int modem_chat_run_script_async(struct modem_chat *chat, const struct modem_chat k_sem_reset(&chat->script_stopped_sem); chat->pending_script = script; - k_work_submit(&chat->script_run_work); + modem_work_submit(&chat->script_run_work); return 0; } @@ -903,7 +905,7 @@ int modem_chat_run_script(struct modem_chat *chat, const struct modem_chat_scrip void modem_chat_script_abort(struct modem_chat *chat) { - k_work_submit(&chat->script_abort_work); + modem_work_submit(&chat->script_abort_work); } void modem_chat_release(struct modem_chat *chat) diff --git a/subsys/modem/modem_cmux.c b/subsys/modem/modem_cmux.c index d5547e03da28..1edf3feaff41 100644 --- a/subsys/modem/modem_cmux.c +++ b/subsys/modem/modem_cmux.c @@ -10,28 +10,36 @@ LOG_MODULE_REGISTER(modem_cmux, CONFIG_MODEM_CMUX_LOG_LEVEL); #include #include #include +#include +#include #include +#include "modem_workqueue.h" + +#define MODEM_CMUX_SOF (0xF9) #define MODEM_CMUX_FCS_POLYNOMIAL (0xE0) #define MODEM_CMUX_FCS_INIT_VALUE (0xFF) #define MODEM_CMUX_EA (0x01) #define MODEM_CMUX_CR (0x02) #define MODEM_CMUX_PF (0x10) -#define MODEM_CMUX_FRAME_SIZE_MAX (0x07) -#define MODEM_CMUX_DATA_SIZE_MIN (0x08) -#define MODEM_CMUX_DATA_FRAME_SIZE_MIN (MODEM_CMUX_FRAME_SIZE_MAX + \ - MODEM_CMUX_DATA_SIZE_MIN) +#define MODEM_CMUX_DATA_SIZE_MIN 8 +#define MODEM_CMUX_DATA_FRAME_SIZE_MIN (MODEM_CMUX_HEADER_SIZE + MODEM_CMUX_DATA_SIZE_MIN) +#define MODEM_CMUX_DATA_FRAME_SIZE_MAX (MODEM_CMUX_HEADER_SIZE + CONFIG_MODEM_CMUX_MTU) -#define MODEM_CMUX_CMD_DATA_SIZE_MAX (0x08) -#define MODEM_CMUX_CMD_FRAME_SIZE_MAX (MODEM_CMUX_FRAME_SIZE_MAX + \ - MODEM_CMUX_CMD_DATA_SIZE_MAX) +/* Biggest supported Multiplexer control commands in UIH frame + * Modem Status Command (MSC) - 5 bytes when Break is included. + * + * PN would be 10 bytes, but that is not implemented + */ +#define MODEM_CMUX_CMD_DATA_SIZE_MAX 5 /* Max size of information field of UIH frame */ +#define MODEM_CMUX_CMD_HEADER_SIZE 2 /* command type + length */ +#define MODEM_CMUX_CMD_FRAME_SIZE_MAX (MODEM_CMUX_HEADER_SIZE + \ + MODEM_CMUX_CMD_DATA_SIZE_MAX) #define MODEM_CMUX_T1_TIMEOUT (K_MSEC(330)) #define MODEM_CMUX_T2_TIMEOUT (K_MSEC(660)) - -#define MODEM_CMUX_EVENT_CONNECTED_BIT (BIT(0)) -#define MODEM_CMUX_EVENT_DISCONNECTED_BIT (BIT(1)) +#define MODEM_CMUX_T3_TIMEOUT (K_SECONDS(CONFIG_MODEM_CMUX_T3_TIMEOUT)) enum modem_cmux_frame_types { MODEM_CMUX_FRAME_TYPE_RR = 0x01, @@ -73,34 +81,268 @@ struct modem_cmux_command_length { struct modem_cmux_command { struct modem_cmux_command_type type; struct modem_cmux_command_length length; - uint8_t value[]; + uint8_t value[MODEM_CMUX_CMD_DATA_SIZE_MAX - 2]; /* Subtract type and length bytes */ +}; + +struct modem_cmux_msc_signals { + uint8_t ea: 1; /**< Last octet, always 1 */ + uint8_t fc: 1; /**< Flow Control */ + uint8_t rtc: 1; /**< Ready to Communicate */ + uint8_t rtr: 1; /**< Ready to Transmit */ + uint8_t res_0: 2; /**< Reserved, set to zero */ + uint8_t ic: 1; /**< Incoming call indicator */ + uint8_t dv: 1; /**< Data Valid */ }; +struct modem_cmux_msc_addr { + uint8_t ea: 1; /**< Last octet, always 1 */ + uint8_t pad_one: 1; /**< Set to 1 */ + uint8_t dlci_address: 6; /**< DLCI channel address */ +}; + +static struct modem_cmux_dlci *modem_cmux_find_dlci(struct modem_cmux *cmux, uint8_t dlci_address); +static void modem_cmux_dlci_notify_transmit_idle(struct modem_cmux *cmux); +static void modem_cmux_tx_bypass(struct modem_cmux *cmux, const uint8_t *data, size_t len); +static void runtime_pm_keepalive(struct modem_cmux *cmux); + +static void set_state(struct modem_cmux *cmux, enum modem_cmux_state state) +{ + cmux->state = state; + k_event_set(&cmux->event, BIT(state)); +} + +static bool wait_state(struct modem_cmux *cmux, enum modem_cmux_state state, k_timeout_t timeout) +{ + return k_event_wait(&cmux->event, BIT(state), false, timeout) == BIT(state); +} + +static bool is_connected(struct modem_cmux *cmux) +{ + return cmux->state == MODEM_CMUX_STATE_CONNECTED; +} + +static bool is_powersaving(struct modem_cmux *cmux) +{ + return cmux->state == MODEM_CMUX_STATE_POWERSAVE; +} + +static bool is_waking_up(struct modem_cmux *cmux) +{ + return cmux->state == MODEM_CMUX_STATE_WAKEUP; +} + +static bool is_transitioning_to_powersave(struct modem_cmux *cmux) +{ + return (cmux->state == MODEM_CMUX_STATE_ENTER_POWERSAVE || + cmux->state == MODEM_CMUX_STATE_CONFIRM_POWERSAVE); +} + +static bool modem_cmux_command_type_is_valid(const struct modem_cmux_command_type type) +{ + /* All commands are only 7 bits, so EA is always set */ + if (type.ea == 0) { + return false; + } + switch (type.value) { + case MODEM_CMUX_COMMAND_NSC: + case MODEM_CMUX_COMMAND_TEST: + case MODEM_CMUX_COMMAND_PSC: + case MODEM_CMUX_COMMAND_RLS: + case MODEM_CMUX_COMMAND_FCOFF: + case MODEM_CMUX_COMMAND_PN: + case MODEM_CMUX_COMMAND_RPN: + case MODEM_CMUX_COMMAND_FCON: + case MODEM_CMUX_COMMAND_CLD: + case MODEM_CMUX_COMMAND_SNC: + case MODEM_CMUX_COMMAND_MSC: + return true; + default: + return false; + } +} + +static bool modem_cmux_command_length_is_valid(const struct modem_cmux_command_length length) +{ + /* All commands are shorter than 127 bytes, so EA is always set */ + if (length.ea == 0) { + return false; + } + if (length.value > (MODEM_CMUX_CMD_DATA_SIZE_MAX - MODEM_CMUX_CMD_HEADER_SIZE)) { + return false; + } + return true; +} + +static bool modem_cmux_command_is_valid(const struct modem_cmux_command *command) +{ + if (!modem_cmux_command_type_is_valid(command->type)) { + return false; + } + if (!modem_cmux_command_length_is_valid(command->length)) { + return false; + } + /* Verify known value sizes as specified in 3GPP TS 27.010 + * section 5.4.6.3 Message Type and Actions + */ + switch (command->type.value) { + case MODEM_CMUX_COMMAND_PN: + return command->length.value == 8; + case MODEM_CMUX_COMMAND_TEST: + return (command->length.value > 0 && + command->length.value <= MODEM_CMUX_CMD_DATA_SIZE_MAX - 2); + case MODEM_CMUX_COMMAND_MSC: + return command->length.value == 2 || command->length.value == 3; + case MODEM_CMUX_COMMAND_NSC: + return command->length.value == 1; + case MODEM_CMUX_COMMAND_RPN: + return command->length.value == 1 || command->length.value == 8; + case MODEM_CMUX_COMMAND_RLS: + return command->length.value == 2; + case MODEM_CMUX_COMMAND_SNC: + return command->length.value == 1 || command->length.value == 3; + default: + return command->length.value == 0; + } +} -static int modem_cmux_wrap_command(struct modem_cmux_command **command, const uint8_t *data, - uint16_t data_len) +static struct modem_cmux_command_type modem_cmux_command_type_decode(const uint8_t byte) { - if ((data == NULL) || (data_len < 2)) { - return -EINVAL; + struct modem_cmux_command_type type = { + .ea = (byte & MODEM_CMUX_EA) ? 1 : 0, + .cr = (byte & MODEM_CMUX_CR) ? 1 : 0, + .value = (byte >> 2) & 0x3F, + }; + + if (type.ea == 0) { + return (struct modem_cmux_command_type){0}; } - (*command) = (struct modem_cmux_command *)data; + return type; +} + +static uint8_t modem_cmux_command_type_encode(const struct modem_cmux_command_type type) +{ + return (type.ea ? MODEM_CMUX_EA : 0) | + (type.cr ? MODEM_CMUX_CR : 0) | + ((type.value & 0x3F) << 2); +} + +static struct modem_cmux_command_length modem_cmux_command_length_decode(const uint8_t byte) +{ + struct modem_cmux_command_length length = { + .ea = (byte & MODEM_CMUX_EA) ? 1 : 0, + .value = (byte >> 1) & 0x7F, + }; - if (((*command)->length.ea == 0) || ((*command)->type.ea == 0)) { - return -EINVAL; + if (length.ea == 0) { + return (struct modem_cmux_command_length){0}; } - if ((*command)->length.value != (data_len - 2)) { - return -EINVAL; + return length; +} + +static uint8_t modem_cmux_command_length_encode(const struct modem_cmux_command_length length) +{ + return (length.ea ? MODEM_CMUX_EA : 0) | + ((length.value & 0x7F) << 1); +} + +static struct modem_cmux_command modem_cmux_command_decode(const uint8_t *data, size_t len) +{ + if (len < 2) { + return (struct modem_cmux_command){0}; } - return 0; + struct modem_cmux_command command = { + .type = modem_cmux_command_type_decode(data[0]), + .length = modem_cmux_command_length_decode(data[1]), + }; + + if (command.type.ea == 0 || command.length.ea == 0 || + command.length.value > MODEM_CMUX_CMD_DATA_SIZE_MAX || + (2 + command.length.value) > len) { + return (struct modem_cmux_command){0}; + } + + memcpy(&command.value[0], &data[2], command.length.value); + + return command; } -static struct modem_cmux_command *modem_cmux_command_wrap(const uint8_t *data) +/** + * @brief Encode command into a shared buffer + * + * Not a thread safe, so can only be used within a workqueue context and data + * must be copied out to a TX ringbuffer. + * + * @param command command to encode + * @param len encoded length of the command is written here + * @return pointer to encoded command buffer on success, NULL on failure + */ +static uint8_t *modem_cmux_command_encode(struct modem_cmux_command *command, uint16_t *len) +{ + static uint8_t buf[MODEM_CMUX_CMD_DATA_SIZE_MAX]; + + __ASSERT_NO_MSG(len != NULL); + __ASSERT_NO_MSG(command != NULL); + __ASSERT_NO_MSG(modem_cmux_command_is_valid(command)); + + buf[0] = modem_cmux_command_type_encode(command->type); + buf[1] = modem_cmux_command_length_encode(command->length); + if (command->length.value > 0) { + memcpy(&buf[2], &command->value[0], command->length.value); + } + *len = 2 + command->length.value; + return buf; +} + +static struct modem_cmux_msc_signals modem_cmux_msc_signals_decode(const uint8_t byte) +{ + struct modem_cmux_msc_signals signals; + + /* 3GPP TS 27.010 MSC signals octet: + * |0 |1 |2 |3 |4 |5 |6 |7 | + * |EA |FC|RTC|RTR|0 |0 |IC|DV| + */ + signals.ea = (byte & BIT(0)) ? 1 : 0; + signals.fc = (byte & BIT(1)) ? 1 : 0; + signals.rtc = (byte & BIT(2)) ? 1 : 0; + signals.rtr = (byte & BIT(3)) ? 1 : 0; + signals.ic = (byte & BIT(6)) ? 1 : 0; + signals.dv = (byte & BIT(7)) ? 1 : 0; + + return signals; +} + +static uint8_t modem_cmux_msc_signals_encode(const struct modem_cmux_msc_signals signals) +{ + return (signals.ea ? BIT(0) : 0) | (signals.fc ? BIT(1) : 0) | + (signals.rtc ? BIT(2) : 0) | (signals.rtr ? BIT(3) : 0) | + (signals.ic ? BIT(6) : 0) | (signals.dv ? BIT(7) : 0); +} + +static struct modem_cmux_msc_addr modem_cmux_msc_addr_decode(const uint8_t byte) +{ + struct modem_cmux_msc_addr addr; + + /* 3GPP TS 27.010 MSC address octet: + * |0 |1 |2 |3 |4 |5 |6 |7 | + * |EA |1 | DLCI | + */ + addr.ea = (byte & BIT(0)) ? 1 : 0; + addr.pad_one = 1; + addr.dlci_address = (byte >> 2) & 0x3F; + + return addr; +} + +static uint8_t modem_cmux_msc_addr_encode(const struct modem_cmux_msc_addr a) { - return (struct modem_cmux_command *)data; + return (a.ea ? BIT(0) : 0) | BIT(1) | + ((a.dlci_address & 0x3F) << 2); } + +#if CONFIG_MODEM_CMUX_LOG_FRAMES static const char *modem_cmux_frame_type_to_str(enum modem_cmux_frame_types frame_type) { switch (frame_type) { @@ -131,8 +373,14 @@ static void modem_cmux_log_frame(const struct modem_cmux_frame *frame, { LOG_DBG("%s ch:%u cr:%u pf:%u type:%s dlen:%u", action, frame->dlci_address, frame->cr, frame->pf, modem_cmux_frame_type_to_str(frame->type), frame->data_len); - LOG_HEXDUMP_DBG(frame->data, hexdump_len, "data:"); + if (hexdump_len > 0) { + LOG_HEXDUMP_DBG(frame->data, hexdump_len, "data:"); + } } +#else +#define modem_cmux_log_frame(frame, action, hexdump_len) \ + do { ARG_UNUSED(frame); ARG_UNUSED(action); ARG_UNUSED(hexdump_len); } while (0) +#endif /* CONFIG_MODEM_CMUX_LOG_FRAMES */ static void modem_cmux_log_transmit_frame(const struct modem_cmux_frame *frame) { @@ -152,7 +400,7 @@ static uint32_t modem_cmux_get_receive_buf_length(struct modem_cmux *cmux) static uint32_t modem_cmux_get_receive_buf_size(struct modem_cmux *cmux) { - return cmux->receive_buf_size; + return cmux->config.receive_buf_size; } static uint32_t modem_cmux_get_transmit_buf_length(struct modem_cmux *cmux) @@ -225,23 +473,21 @@ static void modem_cmux_log_transmit_command(const struct modem_cmux_command *com { LOG_DBG("ea:%u,cr:%u,type:%s", command->type.ea, command->type.cr, modem_cmux_command_type_to_str(command->type.value)); - LOG_HEXDUMP_DBG(command->value, command->length.value, "data:"); } static void modem_cmux_log_received_command(const struct modem_cmux_command *command) { LOG_DBG("ea:%u,cr:%u,type:%s", command->type.ea, command->type.cr, modem_cmux_command_type_to_str(command->type.value)); - LOG_HEXDUMP_DBG(command->value, command->length.value, "data:"); } static void modem_cmux_raise_event(struct modem_cmux *cmux, enum modem_cmux_event event) { - if (cmux->callback == NULL) { + if (cmux->config.callback == NULL) { return; } - cmux->callback(cmux, event, cmux->user_data); + cmux->config.callback(cmux, event, cmux->config.user_data); } static void modem_cmux_bus_callback(struct modem_pipe *pipe, enum modem_pipe_event event, @@ -251,13 +497,20 @@ static void modem_cmux_bus_callback(struct modem_pipe *pipe, enum modem_pipe_eve switch (event) { case MODEM_PIPE_EVENT_RECEIVE_READY: - k_work_schedule(&cmux->receive_work, K_NO_WAIT); + modem_work_schedule(&cmux->receive_work, K_NO_WAIT); break; + case MODEM_PIPE_EVENT_OPENED: + cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_SOF; + modem_work_schedule(&cmux->transmit_work, K_NO_WAIT); + break; case MODEM_PIPE_EVENT_TRANSMIT_IDLE: - k_work_schedule(&cmux->transmit_work, K_NO_WAIT); + /* If we keep UART open in power-save, we should avoid waking up on RX idle */ + if (!cmux->config.close_pipe_on_power_save && is_powersaving(cmux)) { + break; + } + modem_work_schedule(&cmux->transmit_work, K_NO_WAIT); break; - default: break; } @@ -266,18 +519,18 @@ static void modem_cmux_bus_callback(struct modem_pipe *pipe, enum modem_pipe_eve static uint16_t modem_cmux_transmit_frame(struct modem_cmux *cmux, const struct modem_cmux_frame *frame) { - uint8_t buf[MODEM_CMUX_FRAME_SIZE_MAX]; + uint8_t buf[MODEM_CMUX_HEADER_SIZE]; uint8_t fcs; uint16_t space; uint16_t data_len; uint16_t buf_idx; - space = ring_buf_space_get(&cmux->transmit_rb) - MODEM_CMUX_FRAME_SIZE_MAX; + space = ring_buf_space_get(&cmux->transmit_rb) - MODEM_CMUX_HEADER_SIZE; data_len = MIN(space, frame->data_len); data_len = MIN(data_len, CONFIG_MODEM_CMUX_MTU); /* SOF */ - buf[0] = 0xF9; + buf[0] = MODEM_CMUX_SOF; /* DLCI Address (Max 63) */ buf[1] = 0x01 | (frame->cr << 1) | (frame->dlci_address << 2); @@ -313,9 +566,9 @@ static uint16_t modem_cmux_transmit_frame(struct modem_cmux *cmux, /* FCS and EOF will be put on the same call */ buf[0] = fcs; - buf[1] = 0xF9; + buf[1] = MODEM_CMUX_SOF; ring_buf_put(&cmux->transmit_rb, buf, 2); - k_work_schedule(&cmux->transmit_work, K_NO_WAIT); + modem_work_schedule(&cmux->transmit_work, K_NO_WAIT); return data_len; } @@ -323,19 +576,21 @@ static bool modem_cmux_transmit_cmd_frame(struct modem_cmux *cmux, const struct modem_cmux_frame *frame) { uint16_t space; - struct modem_cmux_command *command; + struct modem_cmux_command command; k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); space = ring_buf_space_get(&cmux->transmit_rb); if (space < MODEM_CMUX_CMD_FRAME_SIZE_MAX) { k_mutex_unlock(&cmux->transmit_rb_lock); + LOG_WRN("CMD buffer overflow"); return false; } modem_cmux_log_transmit_frame(frame); - if (modem_cmux_wrap_command(&command, frame->data, frame->data_len) == 0) { - modem_cmux_log_transmit_command(command); + command = modem_cmux_command_decode(frame->data, frame->data_len); + if (modem_cmux_command_is_valid(&command)) { + modem_cmux_log_transmit_command(&command); } modem_cmux_transmit_frame(cmux, frame); @@ -351,7 +606,7 @@ static int16_t modem_cmux_transmit_data_frame(struct modem_cmux *cmux, k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); - if (cmux->flow_control_on == false) { + if (cmux->flow_control_on == false || is_transitioning_to_powersave(cmux)) { k_mutex_unlock(&cmux->transmit_rb_lock); return 0; } @@ -378,7 +633,7 @@ static int16_t modem_cmux_transmit_data_frame(struct modem_cmux *cmux, static void modem_cmux_acknowledge_received_frame(struct modem_cmux *cmux) { - struct modem_cmux_command *command; + struct modem_cmux_command_type command; struct modem_cmux_frame frame; uint8_t data[MODEM_CMUX_CMD_DATA_SIZE_MAX]; @@ -389,8 +644,9 @@ static void modem_cmux_acknowledge_received_frame(struct modem_cmux *cmux) memcpy(&frame, &cmux->frame, sizeof(cmux->frame)); memcpy(data, cmux->frame.data, cmux->frame.data_len); - modem_cmux_wrap_command(&command, data, cmux->frame.data_len); - command->type.cr = 0; + command = modem_cmux_command_type_decode(data[0]); + command.cr = 0; + data[0] = modem_cmux_command_type_encode(command); frame.data = data; frame.data_len = cmux->frame.data_len; @@ -399,10 +655,125 @@ static void modem_cmux_acknowledge_received_frame(struct modem_cmux *cmux) } } +static void modem_cmux_send_psc(struct modem_cmux *cmux) +{ + uint16_t len; + uint8_t *data = modem_cmux_command_encode(&(struct modem_cmux_command){ + .type.ea = 1, + .type.cr = 1, + .type.value = MODEM_CMUX_COMMAND_PSC, + .length.ea = 1, + .length.value = 0, + }, &len); + + if (data == NULL) { + return; + } + + struct modem_cmux_frame frame = { + .dlci_address = 0, + .cr = cmux->initiator, + .pf = true, + .type = MODEM_CMUX_FRAME_TYPE_UIH, + .data = data, + .data_len = len, + }; + + LOG_DBG("Sending PSC command"); + modem_cmux_transmit_cmd_frame(cmux, &frame); +} + +static void modem_cmux_send_msc(struct modem_cmux *cmux, struct modem_cmux_dlci *dlci) +{ + if (cmux == NULL || dlci == NULL) { + return; + } + + struct modem_cmux_msc_addr addr = { + .ea = 1, + .pad_one = 1, + .dlci_address = dlci->dlci_address, + }; + struct modem_cmux_msc_signals signals = { + .ea = 1, + .fc = dlci->rx_full ? 1 : 0, + .rtc = dlci->state == MODEM_CMUX_DLCI_STATE_OPEN ? 1 : 0, + .rtr = dlci->state == MODEM_CMUX_DLCI_STATE_OPEN ? 1 : 0, + .dv = 1, + }; + struct modem_cmux_command cmd = { + .type = { + .ea = 1, + .cr = 1, + .value = MODEM_CMUX_COMMAND_MSC, + }, + .length = { + .ea = 1, + .value = 2, + }, + .value[0] = modem_cmux_msc_addr_encode(addr), + .value[1] = modem_cmux_msc_signals_encode(signals), + }; + + uint16_t len; + uint8_t *data = modem_cmux_command_encode(&cmd, &len); + + if (data == NULL) { + return; + } + + struct modem_cmux_frame frame = { + .dlci_address = 0, + .cr = cmux->initiator, + .pf = false, + .type = MODEM_CMUX_FRAME_TYPE_UIH, + .data = data, + .data_len = len, + }; + + LOG_DBG("Sending MSC command for DLCI %u, FC:%d RTR: %d DV: %d", addr.dlci_address, + signals.fc, signals.rtr, signals.dv); + modem_cmux_transmit_cmd_frame(cmux, &frame); +} + static void modem_cmux_on_msc_command(struct modem_cmux *cmux, struct modem_cmux_command *command) { - if (command->type.cr) { - modem_cmux_acknowledge_received_frame(cmux); + if (!command->type.cr) { + return; + } + + modem_cmux_acknowledge_received_frame(cmux); + + uint8_t len = command->length.value; + + if (len != 2 && len != 3) { + LOG_WRN("Unexpected MSC command length %d", (int)len); + return; + } + + struct modem_cmux_msc_addr msc = modem_cmux_msc_addr_decode(command->value[0]); + struct modem_cmux_msc_signals signals = modem_cmux_msc_signals_decode(command->value[1]); + struct modem_cmux_dlci *dlci = modem_cmux_find_dlci(cmux, msc.dlci_address); + + if (dlci) { + LOG_DBG("MSC command received for DLCI %u", msc.dlci_address); + bool fc_signal = signals.fc || !signals.rtr; + + if (fc_signal != dlci->flow_control) { + if (fc_signal) { + dlci->flow_control = true; + LOG_DBG("DLCI %u flow control ON", dlci->dlci_address); + } else { + dlci->flow_control = false; + LOG_DBG("DLCI %u flow control OFF", dlci->dlci_address); + modem_pipe_notify_transmit_idle(&dlci->pipe); + } + } + /* As we have received MSC, send also our MSC */ + if (!dlci->msc_sent && dlci->state == MODEM_CMUX_DLCI_STATE_OPEN) { + dlci->msc_sent = true; + modem_cmux_send_msc(cmux, dlci); + } } } @@ -412,6 +783,7 @@ static void modem_cmux_on_fcon_command(struct modem_cmux *cmux) cmux->flow_control_on = true; k_mutex_unlock(&cmux->transmit_rb_lock); modem_cmux_acknowledge_received_frame(cmux); + modem_cmux_dlci_notify_transmit_idle(cmux); } static void modem_cmux_on_fcoff_command(struct modem_cmux *cmux) @@ -422,6 +794,17 @@ static void modem_cmux_on_fcoff_command(struct modem_cmux *cmux) modem_cmux_acknowledge_received_frame(cmux); } +static void disconnect(struct modem_cmux *cmux) +{ + LOG_DBG("CMUX disconnected"); + k_work_cancel_delayable(&cmux->disconnect_work); + set_state(cmux, MODEM_CMUX_STATE_DISCONNECTED); + k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); + cmux->flow_control_on = false; + k_mutex_unlock(&cmux->transmit_rb_lock); + modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_DISCONNECTED); +} + static void modem_cmux_on_cld_command(struct modem_cmux *cmux, struct modem_cmux_command *command) { if (command->type.cr) { @@ -435,60 +818,129 @@ static void modem_cmux_on_cld_command(struct modem_cmux *cmux, struct modem_cmux } if (cmux->state == MODEM_CMUX_STATE_DISCONNECTING) { - k_work_cancel_delayable(&cmux->disconnect_work); + disconnect(cmux); + } else { + set_state(cmux, MODEM_CMUX_STATE_DISCONNECTING); + k_work_schedule(&cmux->disconnect_work, MODEM_CMUX_T1_TIMEOUT); } - - cmux->state = MODEM_CMUX_STATE_DISCONNECTED; - k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); - cmux->flow_control_on = false; - k_mutex_unlock(&cmux->transmit_rb_lock); - - modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_DISCONNECTED); - k_event_clear(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT); - k_event_post(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT); } static void modem_cmux_on_control_frame_ua(struct modem_cmux *cmux) { if (cmux->state != MODEM_CMUX_STATE_CONNECTING) { - LOG_DBG("Unexpected UA frame"); + LOG_DBG("Unexpected UA frame in state %d", cmux->state); return; } - cmux->state = MODEM_CMUX_STATE_CONNECTED; + LOG_DBG("CMUX connected"); + set_state(cmux, MODEM_CMUX_STATE_CONNECTED); + cmux->initiator = true; k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); cmux->flow_control_on = true; k_mutex_unlock(&cmux->transmit_rb_lock); k_work_cancel_delayable(&cmux->connect_work); modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_CONNECTED); - k_event_clear(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT); - k_event_post(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT); +} + +static void modem_cmux_respond_unsupported_cmd(struct modem_cmux *cmux) +{ + struct modem_cmux_frame frame = cmux->frame; + struct modem_cmux_command cmd = modem_cmux_command_decode(frame.data, frame.data_len); + + if (!modem_cmux_command_is_valid(&cmd)) { + LOG_WRN("Invalid command"); + return; + } + + + /* 3GPP TS 27.010: 5.4.6.3.8 Non Supported Command Response (NSC) */ + struct modem_cmux_command nsc_cmd = { + .type = { + .ea = 1, + .cr = 0, + .value = MODEM_CMUX_COMMAND_NSC, + }, + .length = { + .ea = 1, + .value = 1, + }, + .value[0] = modem_cmux_command_type_encode(cmd.type), + }; + + uint16_t len; + uint8_t *data = modem_cmux_command_encode(&nsc_cmd, &len); + + if (data == NULL) { + return; + } + + frame.data = data; + frame.data_len = len; + + modem_cmux_transmit_cmd_frame(cmux, &frame); +} + +static void modem_cmux_on_psc_command(struct modem_cmux *cmux) +{ + LOG_DBG("Received power saving command"); + k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); + set_state(cmux, MODEM_CMUX_STATE_CONFIRM_POWERSAVE); + modem_cmux_acknowledge_received_frame(cmux); + k_mutex_unlock(&cmux->transmit_rb_lock); +} + +static void modem_cmux_on_psc_response(struct modem_cmux *cmux) +{ + LOG_DBG("Enter power saving"); + k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); + set_state(cmux, MODEM_CMUX_STATE_POWERSAVE); + k_mutex_unlock(&cmux->transmit_rb_lock); + + if (cmux->config.close_pipe_on_power_save) { + modem_pipe_close_async(cmux->pipe); + } } static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux) { - struct modem_cmux_command *command; + struct modem_cmux_command command; - if ((cmux->state != MODEM_CMUX_STATE_CONNECTED) && - (cmux->state != MODEM_CMUX_STATE_DISCONNECTING)) { + if (cmux->state < MODEM_CMUX_STATE_CONNECTED) { LOG_DBG("Unexpected UIH frame"); return; } - if (modem_cmux_wrap_command(&command, cmux->frame.data, cmux->frame.data_len) < 0) { + command = modem_cmux_command_decode(cmux->frame.data, cmux->frame.data_len); + if (!modem_cmux_command_is_valid(&command)) { LOG_WRN("Invalid command"); return; } - modem_cmux_log_received_command(command); + modem_cmux_log_received_command(&command); - switch (command->type.value) { + if (!command.type.cr) { + LOG_DBG("Received response command"); + switch (command.type.value) { + case MODEM_CMUX_COMMAND_CLD: + modem_cmux_on_cld_command(cmux, &command); + break; + case MODEM_CMUX_COMMAND_PSC: + modem_cmux_on_psc_response(cmux); + break; + default: + /* Responses to other commands are ignored */ + break; + } + return; + } + + switch (command.type.value) { case MODEM_CMUX_COMMAND_CLD: - modem_cmux_on_cld_command(cmux, command); + modem_cmux_on_cld_command(cmux, &command); break; case MODEM_CMUX_COMMAND_MSC: - modem_cmux_on_msc_command(cmux, command); + modem_cmux_on_msc_command(cmux, &command); break; case MODEM_CMUX_COMMAND_FCON: @@ -499,8 +951,13 @@ static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux) modem_cmux_on_fcoff_command(cmux); break; + case MODEM_CMUX_COMMAND_PSC: + modem_cmux_on_psc_command(cmux); + break; + default: LOG_DBG("Unknown control command"); + modem_cmux_respond_unsupported_cmd(cmux); break; } } @@ -524,29 +981,52 @@ static void modem_cmux_connect_response_transmit(struct modem_cmux *cmux) modem_cmux_transmit_cmd_frame(cmux, &frame); } -static void modem_cmux_on_control_frame_sabm(struct modem_cmux *cmux) +static void modem_cmux_dm_response_transmit(struct modem_cmux *cmux) { - modem_cmux_connect_response_transmit(cmux); + if (cmux == NULL) { + return; + } + /* 3GPP TS 27.010: 5.3.3 Disconnected Mode (DM) response */ + struct modem_cmux_frame frame = { + .dlci_address = cmux->frame.dlci_address, + .cr = cmux->frame.cr, + .pf = 1, + .type = MODEM_CMUX_FRAME_TYPE_DM, + .data = NULL, + .data_len = 0, + }; + + LOG_DBG("Send DM response"); + modem_cmux_transmit_cmd_frame(cmux, &frame); +} + +static void modem_cmux_on_control_frame_sabm(struct modem_cmux *cmux) +{ if ((cmux->state == MODEM_CMUX_STATE_CONNECTED) || (cmux->state == MODEM_CMUX_STATE_DISCONNECTING)) { LOG_DBG("Connect request not accepted"); return; } - cmux->state = MODEM_CMUX_STATE_CONNECTED; + LOG_DBG("CMUX connection request received"); + cmux->initiator = false; + set_state(cmux, MODEM_CMUX_STATE_CONNECTED); + modem_cmux_connect_response_transmit(cmux); k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER); cmux->flow_control_on = true; k_mutex_unlock(&cmux->transmit_rb_lock); modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_CONNECTED); - k_event_clear(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT); - k_event_post(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT); } static void modem_cmux_on_control_frame(struct modem_cmux *cmux) { modem_cmux_log_received_frame(&cmux->frame); + if (is_connected(cmux) && cmux->frame.cr == cmux->initiator) { + LOG_DBG("Received a response frame"); + } + switch (cmux->frame.type) { case MODEM_CMUX_FRAME_TYPE_UA: modem_cmux_on_control_frame_ua(cmux); @@ -561,12 +1041,12 @@ static void modem_cmux_on_control_frame(struct modem_cmux *cmux) break; default: - LOG_WRN("Unknown %s frame type", "control"); + LOG_WRN("Unknown %s frame type %d", "control", cmux->frame.type); break; } } -static struct modem_cmux_dlci *modem_cmux_find_dlci(struct modem_cmux *cmux) +static struct modem_cmux_dlci *modem_cmux_find_dlci(struct modem_cmux *cmux, uint8_t dlci_address) { sys_snode_t *node; struct modem_cmux_dlci *dlci; @@ -574,7 +1054,7 @@ static struct modem_cmux_dlci *modem_cmux_find_dlci(struct modem_cmux *cmux) SYS_SLIST_FOR_EACH_NODE(&cmux->dlcis, node) { dlci = (struct modem_cmux_dlci *)node; - if (dlci->dlci_address == cmux->frame.dlci_address) { + if (dlci->dlci_address == dlci_address) { return dlci; } } @@ -582,22 +1062,41 @@ static struct modem_cmux_dlci *modem_cmux_find_dlci(struct modem_cmux *cmux) return NULL; } +static void modem_cmux_on_dlci_frame_dm(struct modem_cmux_dlci *dlci) +{ + dlci->state = MODEM_CMUX_DLCI_STATE_CLOSED; + modem_pipe_notify_closed(&dlci->pipe); + k_work_cancel_delayable(&dlci->close_work); +} + static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci) { + /* Drop invalid UA frames */ + if (dlci->cmux->frame.cr != dlci->cmux->initiator) { + LOG_DBG("Received a response frame, dropping"); + return; + } + switch (dlci->state) { case MODEM_CMUX_DLCI_STATE_OPENING: + LOG_DBG("DLCI %u opened", dlci->dlci_address); dlci->state = MODEM_CMUX_DLCI_STATE_OPEN; modem_pipe_notify_opened(&dlci->pipe); k_work_cancel_delayable(&dlci->open_work); k_mutex_lock(&dlci->receive_rb_lock, K_FOREVER); ring_buf_reset(&dlci->receive_rb); k_mutex_unlock(&dlci->receive_rb_lock); + if (dlci->cmux->initiator) { + modem_cmux_send_msc(dlci->cmux, dlci); + dlci->msc_sent = true; + } else { + dlci->msc_sent = false; + } break; case MODEM_CMUX_DLCI_STATE_CLOSING: - dlci->state = MODEM_CMUX_DLCI_STATE_CLOSED; - modem_pipe_notify_closed(&dlci->pipe); - k_work_cancel_delayable(&dlci->close_work); + LOG_DBG("DLCI %u closed", dlci->dlci_address); + modem_cmux_on_dlci_frame_dm(dlci); break; default: @@ -606,6 +1105,8 @@ static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci) } } + + static void modem_cmux_on_dlci_frame_uih(struct modem_cmux_dlci *dlci) { struct modem_cmux *cmux = dlci->cmux; @@ -623,6 +1124,12 @@ static void modem_cmux_on_dlci_frame_uih(struct modem_cmux_dlci *dlci) LOG_WRN("DLCI %u receive buffer overrun (dropped %u out of %u bytes)", dlci->dlci_address, cmux->frame.data_len - written, cmux->frame.data_len); } + if (written < cmux->frame.data_len || + ring_buf_space_get(&dlci->receive_rb) < MODEM_CMUX_DATA_FRAME_SIZE_MAX) { + LOG_WRN("DLCI %u receive buffer is full", dlci->dlci_address); + dlci->rx_full = true; + modem_cmux_send_msc(cmux, dlci); + } modem_pipe_notify_receive_ready(&dlci->pipe); } @@ -637,7 +1144,9 @@ static void modem_cmux_on_dlci_frame_sabm(struct modem_cmux_dlci *dlci) return; } + LOG_DBG("DLCI %u SABM request accepted, DLCI opened", dlci->dlci_address); dlci->state = MODEM_CMUX_DLCI_STATE_OPEN; + dlci->msc_sent = false; modem_pipe_notify_opened(&dlci->pipe); k_mutex_lock(&dlci->receive_rb_lock, K_FOREVER); ring_buf_reset(&dlci->receive_rb); @@ -651,10 +1160,11 @@ static void modem_cmux_on_dlci_frame_disc(struct modem_cmux_dlci *dlci) modem_cmux_connect_response_transmit(cmux); if (dlci->state != MODEM_CMUX_DLCI_STATE_OPEN) { - LOG_DBG("Unexpected Disc frame"); + modem_cmux_dm_response_transmit(cmux); return; } + LOG_DBG("DLCI %u disconnected", dlci->dlci_address); dlci->state = MODEM_CMUX_DLCI_STATE_CLOSED; modem_pipe_notify_closed(&dlci->pipe); } @@ -665,10 +1175,16 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux) modem_cmux_log_received_frame(&cmux->frame); - dlci = modem_cmux_find_dlci(cmux); + if (cmux->state != MODEM_CMUX_STATE_CONNECTED) { + LOG_DBG("Unexpected DLCI frame in state %d", cmux->state); + return; + } + + dlci = modem_cmux_find_dlci(cmux, cmux->frame.dlci_address); if (dlci == NULL) { - LOG_WRN("Ignoring frame intended for unconfigured DLCI %u.", + LOG_WRN("Frame intended for unconfigured DLCI %u.", cmux->frame.dlci_address); + modem_cmux_dm_response_transmit(cmux); return; } @@ -688,9 +1204,12 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux) case MODEM_CMUX_FRAME_TYPE_DISC: modem_cmux_on_dlci_frame_disc(dlci); break; - + case MODEM_CMUX_FRAME_TYPE_DM: + modem_cmux_on_dlci_frame_dm(dlci); + break; default: - LOG_WRN("Unknown %s frame type", "DLCI"); + LOG_WRN("Unknown %s frame type (%d, DLCI %d)", "DLCI", cmux->frame.type, + cmux->frame.dlci_address); break; } } @@ -701,6 +1220,11 @@ static void modem_cmux_on_frame(struct modem_cmux *cmux) modem_cmux_advertise_receive_buf_stats(cmux); #endif + if (is_powersaving(cmux) || is_waking_up(cmux)) { + set_state(cmux, MODEM_CMUX_STATE_CONNECTED); + LOG_DBG("Exit powersave on received frame"); + } + if (cmux->frame.dlci_address == 0) { modem_cmux_on_control_frame(cmux); } else { @@ -720,8 +1244,8 @@ static void modem_cmux_drop_frame(struct modem_cmux *cmux) #if defined(CONFIG_MODEM_CMUX_LOG_LEVEL_DBG) struct modem_cmux_frame *frame = &cmux->frame; - frame->data = cmux->receive_buf; - modem_cmux_log_frame(frame, "dropped", MIN(frame->data_len, cmux->receive_buf_size)); + frame->data = cmux->config.receive_buf; + modem_cmux_log_frame(frame, "dropped", MIN(frame->data_len, cmux->config.receive_buf_size)); #endif } @@ -731,8 +1255,10 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by switch (cmux->receive_state) { case MODEM_CMUX_RECEIVE_STATE_SOF: - if (byte == 0xF9) { + cmux->frame_header_len = 0; + if (byte == MODEM_CMUX_SOF) { cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_RESYNC; + cmux->frame_header_len++; break; } @@ -743,7 +1269,21 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by * Allow any number of consecutive flags (0xF9). * 0xF9 could also be a valid address field for DLCI 62. */ - if (byte == 0xF9) { + if (byte == MODEM_CMUX_SOF) { + /* Use "header_len" to count SOF bytes, only start transmitting + * flag bytes after receiving more than 3 flags. + * Don't reply flags if we are transitioning between modes or + * if T3 timer is still active (suppress residual flags). + */ + cmux->frame_header_len++; + if ((is_powersaving(cmux) || + (is_connected(cmux) && sys_timepoint_expired(cmux->t3_timepoint))) && + cmux->frame_header_len > 3) { + modem_cmux_tx_bypass(cmux, &(char){MODEM_CMUX_SOF}, 1); + } + if (is_waking_up(cmux)) { + k_work_reschedule(&cmux->transmit_work, K_NO_WAIT); + } break; } @@ -800,7 +1340,7 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by if (cmux->frame.data_len > CONFIG_MODEM_CMUX_MTU) { LOG_ERR("Too large frame"); - cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP; + modem_cmux_drop_frame(cmux); break; } @@ -825,15 +1365,15 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by if (cmux->frame.data_len > CONFIG_MODEM_CMUX_MTU) { LOG_ERR("Too large frame"); - cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP; + modem_cmux_drop_frame(cmux); break; } - if (cmux->frame.data_len > cmux->receive_buf_size) { + if (cmux->frame.data_len > cmux->config.receive_buf_size) { LOG_ERR("Indicated frame data length %u exceeds receive buffer size %u", - cmux->frame.data_len, cmux->receive_buf_size); + cmux->frame.data_len, cmux->config.receive_buf_size); - cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP; + modem_cmux_drop_frame(cmux); break; } @@ -843,8 +1383,8 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by case MODEM_CMUX_RECEIVE_STATE_DATA: /* Copy byte to data */ - if (cmux->receive_buf_len < cmux->receive_buf_size) { - cmux->receive_buf[cmux->receive_buf_len] = byte; + if (cmux->receive_buf_len < cmux->config.receive_buf_size) { + cmux->config.receive_buf[cmux->receive_buf_len] = byte; } cmux->receive_buf_len++; @@ -857,10 +1397,10 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by break; case MODEM_CMUX_RECEIVE_STATE_FCS: - if (cmux->receive_buf_len > cmux->receive_buf_size) { - LOG_WRN("Receive buffer overrun (%u > %u)", - cmux->receive_buf_len, cmux->receive_buf_size); - cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP; + if (cmux->receive_buf_len > cmux->config.receive_buf_size) { + LOG_WRN("Receive buffer overrun (%u > %u)", cmux->receive_buf_len, + cmux->config.receive_buf_size); + modem_cmux_drop_frame(cmux); break; } @@ -877,28 +1417,23 @@ static void modem_cmux_process_received_byte(struct modem_cmux *cmux, uint8_t by if (fcs != byte) { LOG_WRN("Frame FCS error"); - /* Drop frame */ - cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_DROP; + modem_cmux_drop_frame(cmux); break; } cmux->receive_state = MODEM_CMUX_RECEIVE_STATE_EOF; break; - case MODEM_CMUX_RECEIVE_STATE_DROP: - modem_cmux_drop_frame(cmux); - break; - case MODEM_CMUX_RECEIVE_STATE_EOF: /* Validate byte is EOF */ - if (byte != 0xF9) { + if (byte != MODEM_CMUX_SOF) { /* Unexpected byte */ modem_cmux_drop_frame(cmux); break; } /* Process frame */ - cmux->frame.data = cmux->receive_buf; + cmux->frame.data = cmux->config.receive_buf; modem_cmux_on_frame(cmux); /* Await start of next frame */ @@ -916,22 +1451,18 @@ static void modem_cmux_receive_handler(struct k_work *item) struct modem_cmux *cmux = CONTAINER_OF(dwork, struct modem_cmux, receive_work); int ret; + runtime_pm_keepalive(cmux); + /* Receive data from pipe */ - ret = modem_pipe_receive(cmux->pipe, cmux->work_buf, sizeof(cmux->work_buf)); - if (ret < 1) { - if (ret < 0) { - LOG_ERR("Pipe receiving error: %d", ret); + while ((ret = modem_pipe_receive(cmux->pipe, cmux->work_buf, sizeof(cmux->work_buf))) > 0) { + /* Process received data */ + for (int i = 0; i < ret; i++) { + modem_cmux_process_received_byte(cmux, cmux->work_buf[i]); } - return; } - - /* Process received data */ - for (int i = 0; i < ret; i++) { - modem_cmux_process_received_byte(cmux, cmux->work_buf[i]); + if (ret < 0) { + LOG_ERR("Pipe receiving error: %d", ret); } - - /* Reschedule received work */ - k_work_schedule(&cmux->receive_work, K_NO_WAIT); } static void modem_cmux_dlci_notify_transmit_idle(struct modem_cmux *cmux) @@ -941,8 +1472,106 @@ static void modem_cmux_dlci_notify_transmit_idle(struct modem_cmux *cmux) SYS_SLIST_FOR_EACH_NODE(&cmux->dlcis, node) { dlci = (struct modem_cmux_dlci *)node; - modem_pipe_notify_transmit_idle(&dlci->pipe); + if (!dlci->flow_control) { + modem_pipe_notify_transmit_idle(&dlci->pipe); + } + } +} + +static void modem_cmux_runtime_pm_handler(struct k_work *item) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(item); + struct modem_cmux *cmux = CONTAINER_OF(dwork, struct modem_cmux, runtime_pm_work); + + if (!cmux->config.enable_runtime_power_management) { + return; + } + + bool expired = sys_timepoint_expired(cmux->idle_timepoint); + + if (!expired) { + return; + } + + if (is_connected(cmux) && expired) { + LOG_DBG("Idle timeout, entering power saving mode"); + set_state(cmux, MODEM_CMUX_STATE_ENTER_POWERSAVE); + modem_cmux_send_psc(cmux); + k_work_reschedule(&cmux->runtime_pm_work, MODEM_CMUX_T3_TIMEOUT); + return; + } + if (cmux->state == MODEM_CMUX_STATE_ENTER_POWERSAVE) { + LOG_WRN("PSC timeout, not entering power saving mode"); + set_state(cmux, MODEM_CMUX_STATE_CONNECTED); + runtime_pm_keepalive(cmux); + return; + } +} + +static void runtime_pm_keepalive(struct modem_cmux *cmux) +{ + if (cmux == NULL || !cmux->config.enable_runtime_power_management) { + return; + } + + cmux->idle_timepoint = sys_timepoint_calc(cmux->config.idle_timeout); + k_work_reschedule(&cmux->runtime_pm_work, cmux->config.idle_timeout); +} + +/** Transmit bytes bypassing the CMUX buffers. + * Causes modem_cmux_transmit_handler() to be rescheduled as a result of TRANSMIT_IDLE event. + */ +static void modem_cmux_tx_bypass(struct modem_cmux *cmux, const uint8_t *data, size_t len) +{ + if (cmux == NULL) { + return; + } + + modem_pipe_transmit(cmux->pipe, data, len); +} + +static bool powersave_wait_wakeup(struct modem_cmux *cmux) +{ + static const uint8_t wakeup_pattern[] = {MODEM_CMUX_SOF, MODEM_CMUX_SOF, MODEM_CMUX_SOF, + MODEM_CMUX_SOF, MODEM_CMUX_SOF}; + int ret; + + if (is_powersaving(cmux)) { + LOG_DBG("Power saving mode, wake up first"); + set_state(cmux, MODEM_CMUX_STATE_WAKEUP); + + if (cmux->config.close_pipe_on_power_save) { + ret = modem_pipe_open(cmux->pipe, K_FOREVER); + if (ret < 0) { + LOG_ERR("Failed to open pipe for wake up (%d)", ret); + set_state(cmux, MODEM_CMUX_STATE_DISCONNECTED); + modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_DISCONNECTED); + return true; + } + } + + cmux->t3_timepoint = sys_timepoint_calc(MODEM_CMUX_T3_TIMEOUT); + modem_cmux_tx_bypass(cmux, wakeup_pattern, sizeof(wakeup_pattern)); + return true; } + + if (is_waking_up(cmux)) { + if (sys_timepoint_expired(cmux->t3_timepoint)) { + LOG_ERR("Wake up timed out, link dead"); + set_state(cmux, MODEM_CMUX_STATE_DISCONNECTED); + modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_DISCONNECTED); + return true; + } + if (cmux->receive_state != MODEM_CMUX_RECEIVE_STATE_RESYNC) { + /* Retry single flag, until remote wakes up */ + modem_cmux_tx_bypass(cmux, &(uint8_t){MODEM_CMUX_SOF}, 1); + return true; + } + set_state(cmux, MODEM_CMUX_STATE_CONNECTED); + LOG_DBG("Woke up from power saving mode"); + } + + return false; } static void modem_cmux_transmit_handler(struct k_work *item) @@ -960,9 +1589,18 @@ static void modem_cmux_transmit_handler(struct k_work *item) modem_cmux_advertise_transmit_buf_stats(cmux); #endif + if (!is_transitioning_to_powersave(cmux)) { + runtime_pm_keepalive(cmux); + } + while (true) { transmit_rb_empty = ring_buf_is_empty(&cmux->transmit_rb); + if (powersave_wait_wakeup(cmux)) { + k_mutex_unlock(&cmux->transmit_rb_lock); + return; + } + if (transmit_rb_empty) { break; } @@ -987,11 +1625,17 @@ static void modem_cmux_transmit_handler(struct k_work *item) } } - k_mutex_unlock(&cmux->transmit_rb_lock); - if (transmit_rb_empty) { + if (cmux->state == MODEM_CMUX_STATE_CONFIRM_POWERSAVE) { + set_state(cmux, MODEM_CMUX_STATE_POWERSAVE); + LOG_DBG("Entered power saving mode"); + if (cmux->config.close_pipe_on_power_save) { + modem_pipe_close_async(cmux->pipe); + } + } modem_cmux_dlci_notify_transmit_idle(cmux); } + k_mutex_unlock(&cmux->transmit_rb_lock); } static void modem_cmux_connect_handler(struct k_work *item) @@ -1006,7 +1650,8 @@ static void modem_cmux_connect_handler(struct k_work *item) dwork = k_work_delayable_from_work(item); cmux = CONTAINER_OF(dwork, struct modem_cmux, connect_work); - cmux->state = MODEM_CMUX_STATE_CONNECTING; + set_state(cmux, MODEM_CMUX_STATE_CONNECTING); + cmux->initiator = true; static const struct modem_cmux_frame frame = { .dlci_address = 0, @@ -1018,37 +1663,49 @@ static void modem_cmux_connect_handler(struct k_work *item) }; modem_cmux_transmit_cmd_frame(cmux, &frame); - k_work_schedule(&cmux->connect_work, MODEM_CMUX_T1_TIMEOUT); + modem_work_schedule(&cmux->connect_work, MODEM_CMUX_T1_TIMEOUT); } static void modem_cmux_disconnect_handler(struct k_work *item) { struct k_work_delayable *dwork = k_work_delayable_from_work(item); struct modem_cmux *cmux = CONTAINER_OF(dwork, struct modem_cmux, disconnect_work); - struct modem_cmux_command *command; - uint8_t data[2]; - cmux->state = MODEM_CMUX_STATE_DISCONNECTING; + if (cmux->state == MODEM_CMUX_STATE_DISCONNECTING) { + disconnect(cmux); + } else { + set_state(cmux, MODEM_CMUX_STATE_DISCONNECTING); + k_work_schedule(&cmux->disconnect_work, MODEM_CMUX_T1_TIMEOUT); + } + + struct modem_cmux_command command = { + .type.ea = 1, + .type.cr = 1, + .type.value = MODEM_CMUX_COMMAND_CLD, + .length.ea = 1, + .length.value = 0, + }; + + uint16_t len; + uint8_t *data = modem_cmux_command_encode(&command, &len); + + if (data == NULL) { + return; + } - command = modem_cmux_command_wrap(data); - command->type.ea = 1; - command->type.cr = 1; - command->type.value = MODEM_CMUX_COMMAND_CLD; - command->length.ea = 1; - command->length.value = 0; struct modem_cmux_frame frame = { .dlci_address = 0, - .cr = true, + .cr = cmux->initiator, .pf = false, .type = MODEM_CMUX_FRAME_TYPE_UIH, .data = data, - .data_len = sizeof(data), + .data_len = len, }; /* Transmit close down command */ modem_cmux_transmit_cmd_frame(cmux, &frame); - k_work_schedule(&cmux->disconnect_work, MODEM_CMUX_T1_TIMEOUT); + modem_work_schedule(&cmux->disconnect_work, MODEM_CMUX_T1_TIMEOUT); } #if CONFIG_MODEM_STATS @@ -1098,7 +1755,7 @@ static int modem_cmux_dlci_pipe_api_open(void *data) K_SPINLOCK_BREAK; } - k_work_schedule(&dlci->open_work, K_NO_WAIT); + modem_work_schedule(&dlci->open_work, K_NO_WAIT); } return ret; @@ -1110,6 +1767,17 @@ static int modem_cmux_dlci_pipe_api_transmit(void *data, const uint8_t *buf, siz struct modem_cmux *cmux = dlci->cmux; int ret = 0; + if (size == 0 || buf == NULL) { + /* Allow empty transmit request to wake up CMUX */ + runtime_pm_keepalive(cmux); + k_work_reschedule(&cmux->transmit_work, K_NO_WAIT); + return 0; + } + + if (dlci->flow_control) { + return 0; + } + K_SPINLOCK(&cmux->work_lock) { if (!cmux->attached) { ret = -EPERM; @@ -1118,7 +1786,7 @@ static int modem_cmux_dlci_pipe_api_transmit(void *data, const uint8_t *buf, siz struct modem_cmux_frame frame = { .dlci_address = dlci->dlci_address, - .cr = true, + .cr = cmux->initiator, .pf = false, .type = MODEM_CMUX_FRAME_TYPE_UIH, .data = buf, @@ -1144,6 +1812,15 @@ static int modem_cmux_dlci_pipe_api_receive(void *data, uint8_t *buf, size_t siz ret = ring_buf_get(&dlci->receive_rb, buf, size); k_mutex_unlock(&dlci->receive_rb_lock); + + /* Release FC if set */ + if (dlci->rx_full && + ring_buf_space_get(&dlci->receive_rb) >= MODEM_CMUX_DATA_FRAME_SIZE_MAX) { + LOG_DBG("DLCI %u receive buffer is no longer full", dlci->dlci_address); + dlci->rx_full = false; + modem_cmux_send_msc(dlci->cmux, dlci); + } + return ret; } @@ -1164,7 +1841,7 @@ static int modem_cmux_dlci_pipe_api_close(void *data) K_SPINLOCK_BREAK; } - k_work_schedule(&dlci->close_work, K_NO_WAIT); + modem_work_schedule(&dlci->close_work, K_NO_WAIT); } return ret; @@ -1190,10 +1867,11 @@ static void modem_cmux_dlci_open_handler(struct k_work *item) dlci = CONTAINER_OF(dwork, struct modem_cmux_dlci, open_work); dlci->state = MODEM_CMUX_DLCI_STATE_OPENING; + dlci->msc_sent = false; struct modem_cmux_frame frame = { .dlci_address = dlci->dlci_address, - .cr = true, + .cr = dlci->cmux->initiator, .pf = true, .type = MODEM_CMUX_FRAME_TYPE_SABM, .data = NULL, @@ -1201,7 +1879,7 @@ static void modem_cmux_dlci_open_handler(struct k_work *item) }; modem_cmux_transmit_cmd_frame(dlci->cmux, &frame); - k_work_schedule(&dlci->open_work, MODEM_CMUX_T1_TIMEOUT); + modem_work_schedule(&dlci->open_work, MODEM_CMUX_T1_TIMEOUT); } static void modem_cmux_dlci_close_handler(struct k_work *item) @@ -1222,7 +1900,7 @@ static void modem_cmux_dlci_close_handler(struct k_work *item) struct modem_cmux_frame frame = { .dlci_address = dlci->dlci_address, - .cr = true, + .cr = dlci->cmux->initiator, .pf = true, .type = MODEM_CMUX_FRAME_TYPE_DISC, .data = NULL, @@ -1230,7 +1908,7 @@ static void modem_cmux_dlci_close_handler(struct k_work *item) }; modem_cmux_transmit_cmd_frame(cmux, &frame); - k_work_schedule(&dlci->close_work, MODEM_CMUX_T1_TIMEOUT); + modem_work_schedule(&dlci->close_work, MODEM_CMUX_T1_TIMEOUT); } static void modem_cmux_dlci_pipes_release(struct modem_cmux *cmux) @@ -1252,28 +1930,25 @@ void modem_cmux_init(struct modem_cmux *cmux, const struct modem_cmux_config *co __ASSERT_NO_MSG(cmux != NULL); __ASSERT_NO_MSG(config != NULL); __ASSERT_NO_MSG(config->receive_buf != NULL); - __ASSERT_NO_MSG(config->receive_buf_size >= - (CONFIG_MODEM_CMUX_MTU + MODEM_CMUX_FRAME_SIZE_MAX)); + __ASSERT_NO_MSG(config->receive_buf_size >= MODEM_CMUX_DATA_FRAME_SIZE_MAX); __ASSERT_NO_MSG(config->transmit_buf != NULL); - __ASSERT_NO_MSG(config->transmit_buf_size >= - (CONFIG_MODEM_CMUX_MTU + MODEM_CMUX_FRAME_SIZE_MAX)); - - memset(cmux, 0x00, sizeof(*cmux)); - cmux->callback = config->callback; - cmux->user_data = config->user_data; - cmux->receive_buf = config->receive_buf; - cmux->receive_buf_size = config->receive_buf_size; + __ASSERT_NO_MSG(config->transmit_buf_size >= MODEM_CMUX_DATA_FRAME_SIZE_MAX); + + *cmux = (struct modem_cmux){ + .t3_timepoint = sys_timepoint_calc(K_NO_WAIT), + .config = *config, + }; sys_slist_init(&cmux->dlcis); - cmux->state = MODEM_CMUX_STATE_DISCONNECTED; - ring_buf_init(&cmux->transmit_rb, config->transmit_buf_size, config->transmit_buf); + ring_buf_init(&cmux->transmit_rb, cmux->config.transmit_buf_size, + cmux->config.transmit_buf); k_mutex_init(&cmux->transmit_rb_lock); k_work_init_delayable(&cmux->receive_work, modem_cmux_receive_handler); k_work_init_delayable(&cmux->transmit_work, modem_cmux_transmit_handler); k_work_init_delayable(&cmux->connect_work, modem_cmux_connect_handler); k_work_init_delayable(&cmux->disconnect_work, modem_cmux_disconnect_handler); + k_work_init_delayable(&cmux->runtime_pm_work, modem_cmux_runtime_pm_handler); k_event_init(&cmux->event); - k_event_clear(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT); - k_event_post(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT); + set_state(cmux, MODEM_CMUX_STATE_DISCONNECTED); #if CONFIG_MODEM_STATS modem_cmux_init_buf_stats(cmux); @@ -1335,8 +2010,7 @@ int modem_cmux_connect(struct modem_cmux *cmux) return ret; } - if (k_event_wait(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT, false, - MODEM_CMUX_T2_TIMEOUT) == 0) { + if (!wait_state(cmux, MODEM_CMUX_STATE_CONNECTED, MODEM_CMUX_T2_TIMEOUT)) { return -EAGAIN; } @@ -1347,7 +2021,7 @@ int modem_cmux_connect_async(struct modem_cmux *cmux) { int ret = 0; - if (k_event_test(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT)) { + if (cmux->state != MODEM_CMUX_STATE_DISCONNECTED) { return -EALREADY; } @@ -1358,7 +2032,7 @@ int modem_cmux_connect_async(struct modem_cmux *cmux) } if (k_work_delayable_is_pending(&cmux->connect_work) == false) { - k_work_schedule(&cmux->connect_work, K_NO_WAIT); + modem_work_schedule(&cmux->connect_work, K_NO_WAIT); } } @@ -1374,8 +2048,7 @@ int modem_cmux_disconnect(struct modem_cmux *cmux) return ret; } - if (k_event_wait(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT, false, - MODEM_CMUX_T2_TIMEOUT) == 0) { + if (!wait_state(cmux, MODEM_CMUX_STATE_DISCONNECTED, MODEM_CMUX_T2_TIMEOUT)) { return -EAGAIN; } @@ -1386,7 +2059,7 @@ int modem_cmux_disconnect_async(struct modem_cmux *cmux) { int ret = 0; - if (k_event_test(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT)) { + if (cmux->state == MODEM_CMUX_STATE_DISCONNECTED) { return -EALREADY; } @@ -1397,7 +2070,7 @@ int modem_cmux_disconnect_async(struct modem_cmux *cmux) } if (k_work_delayable_is_pending(&cmux->disconnect_work) == false) { - k_work_schedule(&cmux->disconnect_work, K_NO_WAIT); + modem_work_schedule(&cmux->disconnect_work, K_NO_WAIT); } } @@ -1433,7 +2106,6 @@ void modem_cmux_release(struct modem_cmux *cmux) /* Unreference pipe */ cmux->pipe = NULL; - /* Reset events */ - k_event_clear(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT); - k_event_post(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT); + /* Reset state */ + set_state(cmux, MODEM_CMUX_STATE_DISCONNECTED); } diff --git a/subsys/modem/modem_pipe.c b/subsys/modem/modem_pipe.c index bf642b3984dc..ef66b9085ea6 100644 --- a/subsys/modem/modem_pipe.c +++ b/subsys/modem/modem_pipe.c @@ -136,7 +136,7 @@ void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback int modem_pipe_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size) { if (!pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) { - return -EPERM; + return 0; } pipe_clear_events(pipe, PIPE_EVENT_TRANSMIT_IDLE_BIT); @@ -146,7 +146,7 @@ int modem_pipe_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size int modem_pipe_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size) { if (!pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) { - return -EPERM; + return 0; } pipe_clear_events(pipe, PIPE_EVENT_RECEIVE_READY_BIT); diff --git a/subsys/modem/modem_ppp.c b/subsys/modem/modem_ppp.c index 537f198251f7..09b62bdaa11e 100644 --- a/subsys/modem/modem_ppp.c +++ b/subsys/modem/modem_ppp.c @@ -7,8 +7,11 @@ #include #include #include +#include #include +#include "modem_workqueue.h" + #include LOG_MODULE_REGISTER(modem_ppp, CONFIG_MODEM_MODULES_LOG_LEVEL); @@ -48,148 +51,134 @@ static uint16_t modem_ppp_ppp_protocol(struct net_pkt *pkt) return 0; } -static uint8_t modem_ppp_wrap_net_pkt_byte(struct modem_ppp *ppp) +static bool modem_ppp_needs_escape(uint8_t byte) { - uint8_t byte; - - switch (ppp->transmit_state) { - case MODEM_PPP_TRANSMIT_STATE_IDLE: - LOG_WRN("Invalid transmit state"); - return 0; - - /* Writing header */ - case MODEM_PPP_TRANSMIT_STATE_SOF: - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_HDR_FF; - return MODEM_PPP_CODE_DELIMITER; - - case MODEM_PPP_TRANSMIT_STATE_HDR_FF: - net_pkt_cursor_init(ppp->tx_pkt); - ppp->tx_pkt_fcs = modem_ppp_fcs_init(0xFF); - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_HDR_7D; - return 0xFF; - - case MODEM_PPP_TRANSMIT_STATE_HDR_7D: - ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, 0x03); - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_HDR_23; - return MODEM_PPP_CODE_ESCAPE; - - case MODEM_PPP_TRANSMIT_STATE_HDR_23: - if (net_pkt_is_ppp(ppp->tx_pkt) == true) { - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_DATA; - } else { - ppp->tx_pkt_protocol = modem_ppp_ppp_protocol(ppp->tx_pkt); - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_PROTOCOL_HIGH; - } - - return 0x23; - - /* Writing protocol */ - case MODEM_PPP_TRANSMIT_STATE_PROTOCOL_HIGH: - byte = (ppp->tx_pkt_protocol >> 8) & 0xFF; - ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, byte); - - if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) || - (byte < MODEM_PPP_VALUE_ESCAPE)) { - ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE; - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_HIGH; - return MODEM_PPP_CODE_ESCAPE; - } - - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_PROTOCOL_LOW; - return byte; - - case MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_HIGH: - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_PROTOCOL_LOW; - return ppp->tx_pkt_escaped; - - case MODEM_PPP_TRANSMIT_STATE_PROTOCOL_LOW: - byte = ppp->tx_pkt_protocol & 0xFF; - ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, byte); - - if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) || - (byte < MODEM_PPP_VALUE_ESCAPE)) { - ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE; - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_LOW; - return MODEM_PPP_CODE_ESCAPE; - } - - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_DATA; - return byte; - - case MODEM_PPP_TRANSMIT_STATE_ESCAPING_PROTOCOL_LOW: - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_DATA; - return ppp->tx_pkt_escaped; - - /* Writing data */ - case MODEM_PPP_TRANSMIT_STATE_DATA: - (void)net_pkt_read_u8(ppp->tx_pkt, &byte); - ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, byte); - - if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) || - (byte < MODEM_PPP_VALUE_ESCAPE)) { - ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE; - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_DATA; - return MODEM_PPP_CODE_ESCAPE; - } + return (byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) || + (byte < MODEM_PPP_VALUE_ESCAPE); +} - if (net_pkt_remaining_data(ppp->tx_pkt) == 0) { - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_FCS_LOW; - } +static uint32_t modem_ppp_wrap(struct modem_ppp *ppp, uint8_t *buffer, uint32_t available) +{ + uint32_t offset = 0; + uint32_t remaining; + uint16_t protocol; + uint8_t upper; + uint8_t lower; + uint8_t byte; - return byte; + while (offset < available) { + remaining = available - offset; - case MODEM_PPP_TRANSMIT_STATE_ESCAPING_DATA: - if (net_pkt_remaining_data(ppp->tx_pkt) == 0) { - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_FCS_LOW; - } else { + switch (ppp->transmit_state) { + case MODEM_PPP_TRANSMIT_STATE_SOF: + if (remaining < 4) { + /* Insufficient space for constant header prefix */ + goto end; + } + /* Init cursor for later phases */ + net_pkt_cursor_init(ppp->tx_pkt); + /* 3 byte common header */ + buffer[offset++] = MODEM_PPP_CODE_DELIMITER; + buffer[offset++] = 0xFF; + buffer[offset++] = MODEM_PPP_CODE_ESCAPE; + buffer[offset++] = 0x23; + /* Initialise the FCS. + * This value is always the same at this point, so use the constant value. + * Equivelent to: + * ppp->tx_pkt_fcs = modem_ppp_fcs_init(0xFF); + * ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, 0x03); + */ + ARG_UNUSED(modem_ppp_fcs_init); + ppp->tx_pkt_fcs = 0x3DE3; + /* Next state */ + if (net_pkt_is_ppp(ppp->tx_pkt)) { + ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_DATA; + } else { + ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_PROTOCOL; + } + break; + case MODEM_PPP_TRANSMIT_STATE_PROTOCOL: + /* If both protocol bytes need escaping, it could be 4 bytes */ + if (remaining < 4) { + /* Insufficient space for protocol bytes */ + goto end; + } + /* Extract protocol bytes */ + protocol = modem_ppp_ppp_protocol(ppp->tx_pkt); + upper = (protocol >> 8) & 0xFF; + lower = (protocol >> 0) & 0xFF; + /* FCS is computed without the escape/modification */ + ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, upper); + ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, lower); + /* Push protocol bytes (with required escaping) */ + if (modem_ppp_needs_escape(upper)) { + buffer[offset++] = MODEM_PPP_CODE_ESCAPE; + upper ^= MODEM_PPP_VALUE_ESCAPE; + } + buffer[offset++] = upper; + if (modem_ppp_needs_escape(lower)) { + buffer[offset++] = MODEM_PPP_CODE_ESCAPE; + lower ^= MODEM_PPP_VALUE_ESCAPE; + } + buffer[offset++] = lower; + /* Next state */ ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_DATA; + break; + case MODEM_PPP_TRANSMIT_STATE_DATA: + /* Push all data bytes into the buffer */ + while (net_pkt_remaining_data(ppp->tx_pkt) > 0) { + /* Space available, taking into account possible escapes */ + if (remaining < 2) { + goto end; + } + /* Pull next byte we're sending */ + (void)net_pkt_read_u8(ppp->tx_pkt, &byte); + /* FCS is computed without the escape/modification */ + ppp->tx_pkt_fcs = modem_ppp_fcs_update(ppp->tx_pkt_fcs, byte); + /* Push encoded bytes into buffer */ + if (modem_ppp_needs_escape(byte)) { + buffer[offset++] = MODEM_PPP_CODE_ESCAPE; + byte ^= MODEM_PPP_VALUE_ESCAPE; + remaining--; + } + buffer[offset++] = byte; + remaining--; + } + /* Data phase finished */ + ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_EOF; + break; + case MODEM_PPP_TRANSMIT_STATE_EOF: + /* If both FCS bytes need escaping, it could be 5 bytes */ + if (remaining < 5) { + /* Insufficient space for protocol bytes */ + goto end; + } + /* Push FCS (order is [lower, upper] unlike the protocol) */ + ppp->tx_pkt_fcs = modem_ppp_fcs_final(ppp->tx_pkt_fcs); + lower = (ppp->tx_pkt_fcs >> 0) & 0xFF; + upper = (ppp->tx_pkt_fcs >> 8) & 0xFF; + if (modem_ppp_needs_escape(lower)) { + buffer[offset++] = MODEM_PPP_CODE_ESCAPE; + lower ^= MODEM_PPP_VALUE_ESCAPE; + } + buffer[offset++] = lower; + if (modem_ppp_needs_escape(upper)) { + buffer[offset++] = MODEM_PPP_CODE_ESCAPE; + upper ^= MODEM_PPP_VALUE_ESCAPE; + } + buffer[offset++] = upper; + buffer[offset++] = MODEM_PPP_CODE_DELIMITER; + + /* Packet has finished */ + ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_IDLE; + goto end; + default: + LOG_DBG("Invalid transmit state (%d)", ppp->transmit_state); + goto end; } - - return ppp->tx_pkt_escaped; - - /* Writing FCS */ - case MODEM_PPP_TRANSMIT_STATE_FCS_LOW: - ppp->tx_pkt_fcs = modem_ppp_fcs_final(ppp->tx_pkt_fcs); - byte = ppp->tx_pkt_fcs & 0xFF; - - if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) || - (byte < MODEM_PPP_VALUE_ESCAPE)) { - ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE; - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_LOW; - return MODEM_PPP_CODE_ESCAPE; - } - - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_FCS_HIGH; - return byte; - - case MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_LOW: - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_FCS_HIGH; - return ppp->tx_pkt_escaped; - - case MODEM_PPP_TRANSMIT_STATE_FCS_HIGH: - byte = (ppp->tx_pkt_fcs >> 8) & 0xFF; - - if ((byte == MODEM_PPP_CODE_DELIMITER) || (byte == MODEM_PPP_CODE_ESCAPE) || - (byte < MODEM_PPP_VALUE_ESCAPE)) { - ppp->tx_pkt_escaped = byte ^ MODEM_PPP_VALUE_ESCAPE; - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_HIGH; - return MODEM_PPP_CODE_ESCAPE; - } - - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_EOF; - return byte; - - case MODEM_PPP_TRANSMIT_STATE_ESCAPING_FCS_HIGH: - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_EOF; - return ppp->tx_pkt_escaped; - - /* Writing end of frame */ - case MODEM_PPP_TRANSMIT_STATE_EOF: - ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_IDLE; - return MODEM_PPP_CODE_DELIMITER; } - - return 0; +end: + return offset; } static bool modem_ppp_is_byte_expected(uint8_t byte, uint8_t expected_byte) @@ -340,12 +329,12 @@ static void modem_ppp_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_eve switch (event) { case MODEM_PIPE_EVENT_RECEIVE_READY: - k_work_submit(&ppp->process_work); + modem_work_submit(&ppp->process_work); break; case MODEM_PIPE_EVENT_OPENED: case MODEM_PIPE_EVENT_TRANSMIT_IDLE: - k_work_submit(&ppp->send_work); + modem_work_submit(&ppp->send_work); break; default: @@ -356,32 +345,36 @@ static void modem_ppp_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_eve static void modem_ppp_send_handler(struct k_work *item) { struct modem_ppp *ppp = CONTAINER_OF(item, struct modem_ppp, send_work); - uint8_t byte; uint8_t *reserved; uint32_t reserved_size; + uint32_t pushed; int ret; if (ppp->tx_pkt == NULL) { ppp->tx_pkt = k_fifo_get(&ppp->tx_pkt_fifo, K_NO_WAIT); } + if (ring_buf_is_empty(&ppp->transmit_rb)) { + /* Reset to initial state to maximise contiguous claim */ + ring_buf_reset(&ppp->transmit_rb); + } + if (ppp->tx_pkt != NULL) { /* Initialize wrap */ if (ppp->transmit_state == MODEM_PPP_TRANSMIT_STATE_IDLE) { ppp->transmit_state = MODEM_PPP_TRANSMIT_STATE_SOF; } - /* Fill transmit ring buffer */ - while (ring_buf_space_get(&ppp->transmit_rb) > 0) { - byte = modem_ppp_wrap_net_pkt_byte(ppp); - - ring_buf_put(&ppp->transmit_rb, &byte, 1); + /* Claim as much space as possible */ + reserved_size = ring_buf_put_claim(&ppp->transmit_rb, &reserved, UINT32_MAX); + /* Push wrapped data into claimed buffer */ + pushed = modem_ppp_wrap(ppp, reserved, reserved_size); + /* Limit claimed data to what was actually pushed */ + ring_buf_put_finish(&ppp->transmit_rb, pushed); - if (ppp->transmit_state == MODEM_PPP_TRANSMIT_STATE_IDLE) { - net_pkt_unref(ppp->tx_pkt); - ppp->tx_pkt = k_fifo_get(&ppp->tx_pkt_fifo, K_NO_WAIT); - break; - } + if (ppp->transmit_state == MODEM_PPP_TRANSMIT_STATE_IDLE) { + net_pkt_unref(ppp->tx_pkt); + ppp->tx_pkt = k_fifo_get(&ppp->tx_pkt_fifo, K_NO_WAIT); } } @@ -424,7 +417,7 @@ static void modem_ppp_process_handler(struct k_work *item) modem_ppp_process_received_byte(ppp, ppp->receive_buf[i]); } - k_work_submit(&ppp->process_work); + modem_work_submit(&ppp->process_work); } static void modem_ppp_ppp_api_init(struct net_if *iface) @@ -445,12 +438,24 @@ static void modem_ppp_ppp_api_init(struct net_if *iface) static int modem_ppp_ppp_api_start(const struct device *dev) { - return 0; + const struct modem_ppp_config *config = (const struct modem_ppp_config *)dev->config; + + if (config == NULL || config->dev == NULL) { + return 0; + } + + return pm_device_runtime_get(config->dev); } static int modem_ppp_ppp_api_stop(const struct device *dev) { - return 0; + const struct modem_ppp_config *config = (const struct modem_ppp_config *)dev->config; + + if (config == NULL || config->dev == NULL) { + return 0; + } + + return pm_device_runtime_put_async(config->dev, K_NO_WAIT); } static int modem_ppp_ppp_api_send(const struct device *dev, struct net_pkt *pkt) @@ -475,7 +480,7 @@ static int modem_ppp_ppp_api_send(const struct device *dev, struct net_pkt *pkt) net_pkt_ref(pkt); k_fifo_put(&ppp->tx_pkt_fifo, pkt); - k_work_submit(&ppp->send_work); + modem_work_submit(&ppp->send_work); return 0; } diff --git a/subsys/modem/modem_ubx.c b/subsys/modem/modem_ubx.c index 22586b8444d0..89d968caf799 100644 --- a/subsys/modem/modem_ubx.c +++ b/subsys/modem/modem_ubx.c @@ -9,6 +9,8 @@ #include #include +#include "modem_workqueue.h" + #include LOG_MODULE_REGISTER(modem_ubx, CONFIG_MODEM_MODULES_LOG_LEVEL); @@ -19,7 +21,7 @@ static void modem_ubx_pipe_callback(struct modem_pipe *pipe, struct modem_ubx *ubx = (struct modem_ubx *)user_data; if (event == MODEM_PIPE_EVENT_RECEIVE_READY) { - k_work_submit(&ubx->process_work); + modem_work_submit(&ubx->process_work); } } diff --git a/subsys/modem/modem_workqueue.c b/subsys/modem/modem_workqueue.c new file mode 100644 index 000000000000..4fb5d716c5c7 --- /dev/null +++ b/subsys/modem/modem_workqueue.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Embeint Pty Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "modem_workqueue.h" + +static struct k_work_q modem_work_q; +static K_THREAD_STACK_DEFINE(modem_stack_area, CONFIG_MODEM_DEDICATED_WORKQUEUE_STACK_SIZE); + +int modem_work_submit(struct k_work *work) +{ + return k_work_submit_to_queue(&modem_work_q, work); +} + +int modem_work_schedule(struct k_work_delayable *dwork, k_timeout_t delay) +{ + return k_work_schedule_for_queue(&modem_work_q, dwork, delay); +} + +int modem_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay) +{ + return k_work_reschedule_for_queue(&modem_work_q, dwork, delay); +} + +static int modem_work_q_init(void) +{ + /* Boot the dedicated workqueue */ + k_work_queue_init(&modem_work_q); + k_work_queue_start(&modem_work_q, modem_stack_area, K_THREAD_STACK_SIZEOF(modem_stack_area), + CONFIG_MODEM_DEDICATED_WORKQUEUE_PRIORITY, NULL); + k_thread_name_set(k_work_queue_thread_get(&modem_work_q), "modem_workq"); + return 0; +} + +SYS_INIT(modem_work_q_init, POST_KERNEL, 0); diff --git a/subsys/modem/modem_workqueue.h b/subsys/modem/modem_workqueue.h new file mode 100644 index 000000000000..d906ed2e00f0 --- /dev/null +++ b/subsys/modem/modem_workqueue.h @@ -0,0 +1,49 @@ +/** @file + * @brief Modem workqueue header file. + */ + +/* + * Copyright (c) 2025 Embeint Pty Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_MODEM_WORKQUEUE_H_ +#define ZEPHYR_INCLUDE_MODEM_WORKQUEUE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_MODEM_DEDICATED_WORKQUEUE + +int modem_work_submit(struct k_work *work); +int modem_work_schedule(struct k_work_delayable *dwork, k_timeout_t delay); +int modem_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay); + +#else + +static inline int modem_work_submit(struct k_work *work) +{ + return k_work_submit(work); +} + +static inline int modem_work_schedule(struct k_work_delayable *dwork, k_timeout_t delay) +{ + return k_work_schedule(dwork, delay); +} + +static inline int modem_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay) +{ + return k_work_reschedule(dwork, delay); +} + +#endif /* CONFIG_MODEM_DEDICATED_WORKQUEUE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_MODEM_WORKQUEUE_H_ */ diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 270675fe27fd..f86e782ac9f5 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -2719,7 +2719,7 @@ static void tcp_queue_recv_data(struct tcp *conn, struct net_pkt *pkt, } static enum net_verdict tcp_data_received(struct tcp *conn, struct net_pkt *pkt, - size_t *len, bool psh) + size_t *len, bool psh, bool fin) { enum net_verdict ret; @@ -2732,6 +2732,13 @@ static enum net_verdict tcp_data_received(struct tcp *conn, struct net_pkt *pkt, net_stats_update_tcp_seg_recv(conn->iface); conn_ack(conn, *len); + /* In case FIN was received, don't send ACK just yet, FIN,ACK will be + * sent instead. + */ + if (fin) { + return ret; + } + /* Delay ACK response in case of small window or missing PSH, * as described in RFC 813. */ @@ -3143,37 +3150,8 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) } break; - case TCP_ESTABLISHED: - /* full-close */ - if (FL(&fl, &, FIN, th_seq(th) == conn->ack)) { - if (len) { - verdict = tcp_data_get(conn, pkt, &len); - if (verdict == NET_OK) { - /* net_pkt owned by the recv fifo now */ - pkt = NULL; - } - } else { - verdict = NET_OK; - } - - conn_ack(conn, + len + 1); - keep_alive_timer_stop(conn); - - if (net_tcp_seq_cmp(th_ack(th), conn->seq) > 0) { - uint32_t len_acked = th_ack(th) - conn->seq; - - conn_seq(conn, + len_acked); - } - - tcp_out(conn, FIN | ACK); - conn_seq(conn, + 1); - tcp_setup_retransmission(conn); - - tcp_setup_last_ack_timer(conn); - next = TCP_LAST_ACK; - - break; - } + case TCP_ESTABLISHED: { + bool fin = FL(&fl, &, FIN, th_seq(th) == conn->ack); /* Whatever we've received, we know that peer is alive, so reset * the keepalive timer. @@ -3279,11 +3257,21 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) /* We are closing the connection, send a FIN to peer */ if (conn->in_close && conn->send_data_total == 0) { - next = TCP_FIN_WAIT_1; - - k_work_reschedule_for_queue(&tcp_work_q, - &conn->fin_timer, - FIN_TIMEOUT); + if (fin) { + /* If FIN was also present in the processed + * packet, acknowledge that and jump directly + * to TCP_LAST_ACK. + */ + conn_ack(conn, + 1); + next = TCP_LAST_ACK; + tcp_setup_last_ack_timer(conn); + } else { + /* Otherwise, wait for FIN in TCP_FIN_WAIT_1 */ + next = TCP_FIN_WAIT_1; + k_work_reschedule_for_queue(&tcp_work_q, + &conn->fin_timer, + FIN_TIMEOUT); + } tcp_out(conn, FIN | ACK); conn_seq(conn, + 1); @@ -3314,7 +3302,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) data_recv: psh = FL(&fl, &, PSH); - verdict = tcp_data_received(conn, pkt, &len, psh); + verdict = tcp_data_received(conn, pkt, &len, psh, fin); if (verdict == NET_OK) { /* net_pkt owned by the recv fifo now */ pkt = NULL; @@ -3358,7 +3346,19 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) k_sem_give(&conn->tx_sem); } + /* Finally, after all Data/ACK processing, check for FIN flag. */ + if (fin) { + keep_alive_timer_stop(conn); + conn_ack(conn, + 1); + tcp_out(conn, FIN | ACK); + conn_seq(conn, + 1); + tcp_setup_retransmission(conn); + tcp_setup_last_ack_timer(conn); + next = TCP_LAST_ACK; + } + break; + } case TCP_CLOSE_WAIT: /* Half-close is not supported, so do nothing here */ break; diff --git a/subsys/net/l2/ppp/fsm.c b/subsys/net/l2/ppp/fsm.c index 3dd280230883..e5ca056e1c03 100644 --- a/subsys/net/l2/ppp/fsm.c +++ b/subsys/net/l2/ppp/fsm.c @@ -53,6 +53,13 @@ struct net_if *ppp_fsm_iface(struct ppp_fsm *fsm) return ctx->iface; } +static bool ppp_fsm_is_dead(struct ppp_fsm *fsm) +{ + struct ppp_context *ctx = ppp_fsm_ctx(fsm); + + return ctx->phase == PPP_DEAD; +} + static void fsm_send_configure_req(struct ppp_fsm *fsm, bool retransmit) { struct net_pkt *pkt = NULL; @@ -246,6 +253,10 @@ void ppp_fsm_close(struct ppp_fsm *fsm, const uint8_t *reason) case PPP_STOPPING: ppp_change_state(fsm, PPP_CLOSING); + if (ppp_fsm_is_dead(fsm)) { + fsm->retransmits = 0; + k_work_reschedule(&fsm->timer, K_NO_WAIT); + } break; default: diff --git a/subsys/net/l2/ppp/lcp.c b/subsys/net/l2/ppp/lcp.c index a62a9e52541e..49b0b53ab7e7 100644 --- a/subsys/net/l2/ppp/lcp.c +++ b/subsys/net/l2/ppp/lcp.c @@ -163,7 +163,12 @@ static void lcp_open(struct ppp_context *ctx) static void lcp_close(struct ppp_context *ctx, const uint8_t *reason) { if (ctx->phase != PPP_DEAD) { - ppp_change_phase(ctx, PPP_TERMINATE); + if (ctx->phase == PPP_ESTABLISH) { + /* Link is not established yet, so we can go directly to DEAD */ + ppp_change_phase(ctx, PPP_DEAD); + } else { + ppp_change_phase(ctx, PPP_TERMINATE); + } } ppp_fsm_close(&ctx->lcp.fsm, reason); diff --git a/subsys/net/l2/wifi/CMakeLists.txt b/subsys/net/l2/wifi/CMakeLists.txt index f91964d9d83a..c3f12fe132cf 100644 --- a/subsys/net/l2/wifi/CMakeLists.txt +++ b/subsys/net/l2/wifi/CMakeLists.txt @@ -28,6 +28,8 @@ if(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE AND CONFIG_NET_L2_WIFI_SHELL) # Wi-Fi Enterprise test certificates handling set(gen_inc_dir ${ZEPHYR_BINARY_DIR}/misc/generated) set(gen_dir ${gen_inc_dir}/wifi_enterprise_test_certs) + zephyr_get(WIFI_TEST_CERTS_DIR SYSBUILD GLOBAL) + message(DEBUG "WIFI_TEST_CERTS_DIR is set to ${WIFI_TEST_CERTS_DIR}") if(NOT DEFINED WIFI_TEST_CERTS_DIR) set(WIFI_TEST_CERTS_DIR ${ZEPHYR_BASE}/samples/net/wifi/test_certs/rsa3k) endif() diff --git a/subsys/net/lib/dns/llmnr_responder.c b/subsys/net/lib/dns/llmnr_responder.c index c8b1500b1b01..7dfa682f53d6 100644 --- a/subsys/net/lib/dns/llmnr_responder.c +++ b/subsys/net/lib/dns/llmnr_responder.c @@ -192,23 +192,19 @@ static void setup_dns_hdr(uint8_t *buf, uint16_t answers, uint16_t dns_id) static void add_question(struct net_buf *query, enum dns_rr_type qtype) { - char *dot = query->data + DNS_MSG_HEADER_SIZE; - char *prev = NULL; + char *dot = query->data + DNS_MSG_HEADER_SIZE + 1; + char *prev = query->data + DNS_MSG_HEADER_SIZE; uint16_t offset; - while ((dot = strchr(dot, '.'))) { - if (!prev) { - prev = dot++; - continue; - } + /* For the length of the first label. */ + query->len += 1; + while ((dot = strchr(dot, '.')) != NULL) { *prev = dot - prev - 1; prev = dot++; } - if (prev) { - *prev = strlen(prev) - 1; - } + *prev = strlen(prev + 1); offset = DNS_MSG_HEADER_SIZE + query->len + 1; UNALIGNED_PUT(htons(qtype), (uint16_t *)(query->data+offset)); @@ -245,14 +241,15 @@ static int create_answer(enum dns_rr_type qtype, /* Prepare the response into the query buffer: move the name * query buffer has to get enough free space: dns_hdr + query + answer */ - if ((net_buf_max_len(query) - query->len) < (DNS_MSG_HEADER_SIZE + + if ((net_buf_max_len(query) - query->len) < (DNS_MSG_HEADER_SIZE + 1 + (DNS_QTYPE_LEN + DNS_QCLASS_LEN) * 2 + DNS_TTL_LEN + DNS_RDLENGTH_LEN + addr_len + query->len)) { return -ENOBUFS; } - memmove(query->data + DNS_MSG_HEADER_SIZE, query->data, query->len); + /* +1 for the initial label length */ + memmove(query->data + DNS_MSG_HEADER_SIZE + 1, query->data, query->len); setup_dns_hdr(query->data, 1, dns_id); @@ -488,8 +485,8 @@ static int dns_read(int sock, result->data, ret); /* If the query matches to our hostname, then send reply */ - if (!strncasecmp(hostname, result->data + 1, hostname_len) && - (result->len - 1) >= hostname_len) { + if (!strncasecmp(hostname, result->data, hostname_len) && + (result->len) >= hostname_len) { NET_DBG("%s query to our hostname %s", "LLMNR", hostname); ret = send_response(sock, src_addr, addrlen, result, qtype, diff --git a/subsys/net/lib/dns/mdns_responder.c b/subsys/net/lib/dns/mdns_responder.c index a867cd079a13..e60ab9b70029 100644 --- a/subsys/net/lib/dns/mdns_responder.c +++ b/subsys/net/lib/dns/mdns_responder.c @@ -274,23 +274,19 @@ static void setup_dns_hdr(uint8_t *buf, uint16_t answers) static void add_answer(struct net_buf *query, enum dns_rr_type qtype, uint32_t ttl, uint16_t addr_len, uint8_t *addr) { - char *dot = query->data + DNS_MSG_HEADER_SIZE; - char *prev = NULL; + char *dot = query->data + DNS_MSG_HEADER_SIZE + 1; + char *prev = query->data + DNS_MSG_HEADER_SIZE; uint16_t offset; - while ((dot = strchr(dot, '.'))) { - if (!prev) { - prev = dot++; - continue; - } + /* For the length of the first label. */ + query->len += 1; + while ((dot = strchr(dot, '.')) != NULL) { *prev = dot - prev - 1; prev = dot++; } - if (prev) { - *prev = strlen(prev) - 1; - } + *prev = strlen(prev + 1); /* terminator byte (0x00) */ query->len += 1; @@ -322,14 +318,15 @@ static int create_answer(int sock, /* Prepare the response into the query buffer: move the name * query buffer has to get enough free space: dns_hdr + answer */ - if ((net_buf_max_len(query) - query->len) < (DNS_MSG_HEADER_SIZE + + if ((net_buf_max_len(query) - query->len) < (DNS_MSG_HEADER_SIZE + 1 + DNS_QTYPE_LEN + DNS_QCLASS_LEN + DNS_TTL_LEN + DNS_RDLENGTH_LEN + addr_len)) { return -ENOBUFS; } - memmove(query->data + DNS_MSG_HEADER_SIZE, query->data, query->len); + /* +1 for the initial label length */ + memmove(query->data + DNS_MSG_HEADER_SIZE + 1, query->data, query->len); setup_dns_hdr(query->data, 1); @@ -641,7 +638,7 @@ static int dns_read(int sock, } /* Handle only .local queries */ - lquery = strrchr(result->data + 1, '.'); + lquery = strrchr(result->data, '.'); if (!lquery || memcmp(lquery, (const void *){ ".local" }, 7)) { continue; } @@ -654,9 +651,9 @@ static int dns_read(int sock, * We skip the first dot, and make sure there is dot after * matching hostname. */ - if (!strncasecmp(hostname, result->data + 1, hostname_len) && - (result->len - 1) >= hostname_len && - &(result->data + 1)[hostname_len] == lquery) { + if (!strncasecmp(hostname, result->data, hostname_len) && + (result->len) >= hostname_len && + &result->data[hostname_len] == lquery) { NET_DBG("%s %s %s to our hostname %s%s", "mDNS", family == AF_INET ? "IPv4" : "IPv6", "query", hostname, ".local"); diff --git a/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c b/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c index 2ff337eef343..617dec4b4d26 100644 --- a/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c +++ b/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c @@ -22,10 +22,15 @@ int mqtt_client_tls_connect(struct mqtt_client *client) { const struct sockaddr *broker = client->broker; struct mqtt_sec_config *tls_config = &client->transport.tls.config; + int type = SOCK_STREAM; int ret; + if (tls_config->set_native_tls) { + type |= SOCK_NATIVE_TLS; + } + client->transport.tls.sock = zsock_socket(broker->sa_family, - SOCK_STREAM, IPPROTO_TLS_1_2); + type, IPPROTO_TLS_1_2); if (client->transport.tls.sock < 0) { return -errno; } @@ -109,6 +114,16 @@ int mqtt_client_tls_connect(struct mqtt_client *client) } } + if (tls_config->session_cache == TLS_SESSION_CACHE_ENABLED) { + ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS, + TLS_SESSION_CACHE, + &tls_config->session_cache, + sizeof(tls_config->session_cache)); + if (ret < 0) { + goto error; + } + } + if (tls_config->cert_nocopy != TLS_CERT_NOCOPY_NONE) { ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS, TLS_CERT_NOCOPY, &tls_config->cert_nocopy, diff --git a/subsys/net/lib/websocket/websocket.c b/subsys/net/lib/websocket/websocket.c index 2efb16bfac89..d682fd4b5dc2 100644 --- a/subsys/net/lib/websocket/websocket.c +++ b/subsys/net/lib/websocket/websocket.c @@ -34,7 +34,12 @@ LOG_MODULE_REGISTER(net_websocket, CONFIG_NET_WEBSOCKET_LOG_LEVEL); #include #include #include + +#ifdef CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT +#include +#else #include +#endif /* CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT */ #include "net_private.h" #include "sockets_internal.h" @@ -253,6 +258,10 @@ int websocket_connect(int sock, struct websocket_request *wreq, "Sec-WebSocket-Version: 13\r\n", NULL }; +#ifdef CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT + psa_status_t psa_status; + size_t hash_length; +#endif /* CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT */ fd = -1; @@ -280,8 +289,23 @@ int websocket_connect(int sock, struct websocket_request *wreq, ctx->http_cb = wreq->http_cb; ctx->is_client = 1; - mbedtls_sha1((const unsigned char *)&rnd_value, sizeof(rnd_value), - sec_accept_key); +#ifdef CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT + psa_status = psa_hash_compute(PSA_ALG_SHA_1, (const uint8_t *)&rnd_value, sizeof(rnd_value), + sec_accept_key, sizeof(sec_accept_key), &hash_length); + if (psa_status != PSA_SUCCESS) { + NET_DBG("[%p] Cannot calculate sha1 (%d)", ctx, psa_status); + ret = -EPROTO; + goto out; + } +#else + ret = mbedtls_sha1((const unsigned char *)&rnd_value, sizeof(rnd_value), sec_accept_key); + if (ret != 0) { + NET_DBG("[%p] Cannot calculate sha1 (%d)", ctx, ret); + ret = -EPROTO; + goto out; + } +#endif /* CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT */ + ret = base64_encode(sec_ws_key + sizeof("Sec-Websocket-Key: ") - 1, sizeof(sec_ws_key) - @@ -344,7 +368,22 @@ int websocket_connect(int sock, struct websocket_request *wreq, strncpy(key_accept + key_len, WS_MAGIC, olen); /* This SHA-1 value is then checked when we receive the response */ - mbedtls_sha1(key_accept, olen + key_len, sec_accept_key); +#ifdef CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT + psa_status = psa_hash_compute(PSA_ALG_SHA_1, (const uint8_t *)key_accept, olen + key_len, + sec_accept_key, sizeof(sec_accept_key), &hash_length); + if (psa_status != PSA_SUCCESS) { + NET_DBG("[%p] Cannot calculate sha1 (%d)", ctx, psa_status); + ret = -EPROTO; + goto out; + } +#else + ret = mbedtls_sha1(key_accept, olen + key_len, sec_accept_key); + if (ret != 0) { + NET_DBG("[%p] Cannot calculate sha1 (%d)", ctx, ret); + ret = -EPROTO; + goto out; + } +#endif /* CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT */ ret = http_client_req(sock, &req, timeout, ctx); if (ret < 0) { diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index af0409de559a..676f4ef229f5 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -10,6 +10,14 @@ config HAS_PM This option must be selected by SoCs that provide PM hooks, that is, calls to configure low-power states. +config HAS_PM_S2RAM_CUSTOM_MARKING + bool + depends on HAS_PM + help + By default a magic word in RAM is used to mark entering suspend-to-RAM. If this + option is selected, a custom implementation of functions which handle the marking + must be provided. + config PM bool "System Power Management" depends on SYS_CLOCK_EXISTS && HAS_PM @@ -33,21 +41,17 @@ config PM_STATS help Enable System Power Management Stats. +DT_POWER_STATE_COMPAT := zephyr,power-state + config PM_S2RAM - bool "Suspend-to-RAM (S2RAM)" + bool + default y depends on ARCH_HAS_SUSPEND_TO_RAM + depends on $(dt_compat_any_has_prop,$(DT_POWER_STATE_COMPAT),power-state-name,suspend-to-ram) help - This option enables suspend-to-RAM (S2RAM). - When enabled on Cortex-M, and a 'zephyr,memory-region' compatible node with nodelabel - 'pm_s2ram' is defined in DT, _cpu_context symbol (located in arch/arm/core/cortex_m/pm_s2ram.c) - is placed in linker section given by 'zephyr,memory-region' property of aforementioned node. - -config PM_S2RAM_CUSTOM_MARKING - bool "Use custom marking functions" - depends on PM_S2RAM - help - By default a magic word in RAM is used to mark entering suspend-to-RAM. Enabling - this option allows custom implementation of functions which handle the marking. + This option enables the SoC specific implementations of suspend-to-ram (S2RAM) + sleep states if PM is enabled and one or more suspend-to-ram sleep states are + enabled in the devicetree. config PM_NEED_ALL_DEVICES_IDLE bool "System Low Power Mode Needs All Devices Idle" @@ -177,6 +181,15 @@ endif #PM_DEVICE_RUNTIME_USE_DEDICATED_WQ endchoice endif # PM_DEVICE_RUNTIME_ASYNC + +config PM_DEVICE_RUNTIME_DEFAULT_ENABLE + bool "PM device runtime enable by default" + help + Enable PM device runtime by default for all devices when they are + initialized. This option is identical to adding the devicetree + property zephyr,pm-device-runtime-auto to all nodes in the + devicetree. + endif # PM_DEVICE_RUNTIME config PM_DEVICE_SHELL diff --git a/subsys/pm/device.c b/subsys/pm/device.c index 2d7bb3176c36..c74eea661f05 100644 --- a/subsys/pm/device.c +++ b/subsys/pm/device.c @@ -388,7 +388,8 @@ int pm_device_driver_init(const struct device *dev, /* If device will have PM device runtime enabled */ if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) && - atomic_test_bit(&pm->flags, PM_DEVICE_FLAG_RUNTIME_AUTO)) { + (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME_DEFAULT_ENABLE) || + atomic_test_bit(&pm->flags, PM_DEVICE_FLAG_RUNTIME_AUTO))) { return 0; } diff --git a/subsys/pm/device_runtime.c b/subsys/pm/device_runtime.c index 490d7de49334..104d1fdb5955 100644 --- a/subsys/pm/device_runtime.c +++ b/subsys/pm/device_runtime.c @@ -401,10 +401,15 @@ int pm_device_runtime_auto_enable(const struct device *dev) { struct pm_device_base *pm = dev->pm_base; - /* No action needed if PM_DEVICE_FLAG_RUNTIME_AUTO is not enabled */ - if (!pm || !atomic_test_bit(&pm->flags, PM_DEVICE_FLAG_RUNTIME_AUTO)) { + if (!pm) { return 0; } + + if (!IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME_DEFAULT_ENABLE) && + !atomic_test_bit(&pm->flags, PM_DEVICE_FLAG_RUNTIME_AUTO)) { + return 0; + } + return pm_device_runtime_enable(dev); } diff --git a/subsys/shell/backends/shell_uart.c b/subsys/shell/backends/shell_uart.c index 1d19ce19a318..a65c2fb16aef 100644 --- a/subsys/shell/backends/shell_uart.c +++ b/subsys/shell/backends/shell_uart.c @@ -13,6 +13,7 @@ #include #include #include +#include #define LOG_MODULE_NAME shell_uart LOG_MODULE_REGISTER(shell_uart); @@ -290,6 +291,7 @@ static int init(const struct shell_transport *transport, void *context) { struct shell_uart_common *common = (struct shell_uart_common *)transport->ctx; + int ret; common->dev = (const struct device *)config; common->handler = evt_handler; @@ -300,6 +302,11 @@ static int init(const struct shell_transport *transport, k_fifo_init(&common->smp.buf_ready); #endif + ret = pm_device_runtime_get(common->dev); + if (ret < 0) { + return ret; + } + if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_ASYNC)) { async_init((struct shell_uart_async *)transport->ctx); } else if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN)) { @@ -331,6 +338,8 @@ static void polling_uninit(struct shell_uart_polling *sh_uart) static int uninit(const struct shell_transport *transport) { + struct shell_uart_common *common = (struct shell_uart_common *)transport->ctx; + if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_ASYNC)) { async_uninit((struct shell_uart_async *)transport->ctx); } else if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN)) { @@ -339,7 +348,7 @@ static int uninit(const struct shell_transport *transport) polling_uninit((struct shell_uart_polling *)transport->ctx); } - return 0; + return pm_device_runtime_put(common->dev); } static int enable(const struct shell_transport *transport, bool blocking_tx) diff --git a/subsys/storage/flash_map/flash_map_default.c b/subsys/storage/flash_map/flash_map_default.c index c0514d28a12c..6b1edfbbaef5 100644 --- a/subsys/storage/flash_map/flash_map_default.c +++ b/subsys/storage/flash_map/flash_map_default.c @@ -40,6 +40,7 @@ */ const struct flash_area default_flash_map[] = { DT_FOREACH_STATUS_OKAY(fixed_partitions, FOREACH_PARTITION) + DT_FOREACH_STATUS_OKAY(fixed_subpartitions, FOREACH_PARTITION) }; const int flash_map_entries = ARRAY_SIZE(default_flash_map); @@ -63,11 +64,11 @@ const struct flash_area *flash_map = default_flash_map; #define FOR_EACH_PARTITION_TABLE(table) DT_FOREACH_CHILD(table, DEFINE_PARTITION) DT_FOREACH_STATUS_OKAY(fixed_partitions, FOR_EACH_PARTITION_TABLE) -#define DEFINE_SUB_PARTITION(part) DEFINE_SUB_PARTITION_1(part, DT_DEP_ORD(part)) -#define DEFINE_SUB_PARTITION_1(part, ord) \ +#define DEFINE_SUBPARTITION(part) DEFINE_SUBPARTITION_1(part, DT_DEP_ORD(part)) +#define DEFINE_SUBPARTITION_1(part, ord) \ COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_MTD_FROM_FIXED_SUBPARTITION(part)), \ - (DEFINE_SUB_PARTITION_0(part, ord)), ()) -#define DEFINE_SUB_PARTITION_0(part, ord) \ + (DEFINE_SUBPARTITION_0(part, ord)), ()) +#define DEFINE_SUBPARTITION_0(part, ord) \ const struct flash_area DT_CAT(global_fixed_subpartition_ORD_, ord) = { \ .fa_id = DT_FIXED_PARTITION_ID(part), \ .fa_off = DT_REG_ADDR(part), \ @@ -75,5 +76,5 @@ DT_FOREACH_STATUS_OKAY(fixed_partitions, FOR_EACH_PARTITION_TABLE) .fa_size = DT_REG_SIZE(part), \ }; -#define FOR_EACH_SUB_PARTITION_TABLE(table) DT_FOREACH_CHILD(table, DEFINE_SUB_PARTITION) -DT_FOREACH_STATUS_OKAY(fixed_subpartitions, FOR_EACH_SUB_PARTITION_TABLE) +#define FOR_EACH_SUBPARTITION_TABLE(table) DT_FOREACH_CHILD(table, DEFINE_SUBPARTITION) +DT_FOREACH_STATUS_OKAY(fixed_subpartitions, FOR_EACH_SUBPARTITION_TABLE) diff --git a/subsys/usb/device_next/class/Kconfig.hid b/subsys/usb/device_next/class/Kconfig.hid index 8e3133a1dde8..a6f2980ec3ab 100644 --- a/subsys/usb/device_next/class/Kconfig.hid +++ b/subsys/usb/device_next/class/Kconfig.hid @@ -30,6 +30,11 @@ config USBD_HID_INIT_PRIORITY help HID device initialization priority +config USBD_HID_SET_POLLING_PERIOD + bool "Allow to set polling period at runtime" + help + Allow to set input or output report polling period at runtime. + module = USBD_HID module-str = usbd hid source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c index d978aea0d27c..2ea3a08db763 100644 --- a/subsys/usb/device_next/class/usbd_hid.c +++ b/subsys/usb/device_next/class/usbd_hid.c @@ -57,6 +57,7 @@ struct usbd_hid_descriptor { }; enum { + HID_DEV_CLASS_INITIALIZED, HID_DEV_CLASS_ENABLED, }; @@ -503,7 +504,14 @@ static int usbd_hid_init(struct usbd_class_data *const c_data) const struct device *dev = usbd_class_get_private(c_data); const struct hid_device_config *dcfg = dev->config; struct usbd_hid_descriptor *const desc = dcfg->desc; + struct hid_device_data *const ddata = dev->data; + if (ddata->ops == NULL || ddata->rdesc == NULL || !ddata->rsize) { + LOG_ERR("HID device does not seem to be registered"); + return -EINVAL; + } + + atomic_set_bit(&ddata->state, HID_DEV_CLASS_INITIALIZED); LOG_DBG("HID class %s init", c_data->name); if (dcfg->if_desc_data != NULL && desc->if0.iInterface == 0) { @@ -519,6 +527,10 @@ static int usbd_hid_init(struct usbd_class_data *const c_data) static void usbd_hid_shutdown(struct usbd_class_data *const c_data) { + const struct device *dev = usbd_class_get_private(c_data); + struct hid_device_data *const ddata = dev->data; + + atomic_clear_bit(&ddata->state, HID_DEV_CLASS_INITIALIZED); LOG_DBG("HID class %s shutdown", c_data->name); } @@ -620,6 +632,56 @@ static int hid_dev_submit_report(const struct device *dev, return 0; } +static inline int hid_dev_set_out_polling(const struct device *dev, + const unsigned int period_us) +{ + const struct hid_device_config *const dcfg = dev->config; + struct hid_device_data *const ddata = dev->data; + struct usbd_hid_descriptor *const desc = dcfg->desc; + + if (atomic_test_bit(&ddata->state, HID_DEV_CLASS_INITIALIZED)) { + return -EBUSY; + } + + if (USBD_SUPPORTS_HIGH_SPEED) { + if (desc->hs_out_ep.bLength == 0) { + /* This device does not have output reports. */ + return -ENOTSUP; + } + + desc->hs_out_ep.bInterval = USB_HS_INT_EP_INTERVAL(period_us); + } + + if (desc->out_ep.bLength == 0) { + /* This device does not have output reports. */ + return -ENOTSUP; + } + + desc->out_ep.bInterval = USB_FS_INT_EP_INTERVAL(period_us); + + return 0; +} + +static inline int hid_dev_set_in_polling(const struct device *dev, + const unsigned int period_us) +{ + const struct hid_device_config *const dcfg = dev->config; + struct hid_device_data *const ddata = dev->data; + struct usbd_hid_descriptor *const desc = dcfg->desc; + + if (atomic_test_bit(&ddata->state, HID_DEV_CLASS_INITIALIZED)) { + return -EBUSY; + } + + if (USBD_SUPPORTS_HIGH_SPEED) { + desc->hs_in_ep.bInterval = USB_HS_INT_EP_INTERVAL(period_us); + } + + desc->in_ep.bInterval = USB_FS_INT_EP_INTERVAL(period_us); + + return 0; +} + static int hid_dev_register(const struct device *dev, const uint8_t *const rdesc, const uint16_t rsize, const struct hid_device_ops *const ops) @@ -628,7 +690,7 @@ static int hid_dev_register(const struct device *dev, struct hid_device_data *const ddata = dev->data; struct usbd_hid_descriptor *const desc = dcfg->desc; - if (atomic_test_bit(&ddata->state, HID_DEV_CLASS_ENABLED)) { + if (atomic_test_bit(&ddata->state, HID_DEV_CLASS_INITIALIZED)) { return -EALREADY; } @@ -694,6 +756,10 @@ struct usbd_class_api usbd_hid_api = { static const struct hid_device_driver_api hid_device_api = { .submit_report = hid_dev_submit_report, .dev_register = hid_dev_register, +#if CONFIG_USBD_HID_SET_POLLING_PERIOD + .set_out_polling = hid_dev_set_out_polling, + .set_in_polling = hid_dev_set_in_polling, +#endif }; #include "usbd_hid_macros.h" diff --git a/subsys/usb/device_next/class/usbd_hid_api.c b/subsys/usb/device_next/class/usbd_hid_api.c index f2efa4e3cb1e..fd9f27a23ba9 100644 --- a/subsys/usb/device_next/class/usbd_hid_api.c +++ b/subsys/usb/device_next/class/usbd_hid_api.c @@ -34,6 +34,28 @@ int hid_device_register(const struct device *dev, return api->dev_register(dev, rdesc, rsize, ops); } +int hid_device_set_in_polling(const struct device *dev, const unsigned int period_us) +{ + const struct hid_device_driver_api *const api = dev->api; + + if (IS_ENABLED(CONFIG_USBD_HID_SET_POLLING_PERIOD)) { + return api->set_in_polling(dev, period_us); + } + + return -ENOTSUP; +} + +int hid_device_set_out_polling(const struct device *dev, const unsigned int period_us) +{ + const struct hid_device_driver_api *const api = dev->api; + + if (IS_ENABLED(CONFIG_USBD_HID_SET_POLLING_PERIOD)) { + return api->set_out_polling(dev, period_us); + } + + return -ENOTSUP; +} + /* Legacy HID API wrapper below */ struct legacy_wrapper { diff --git a/subsys/usb/device_next/class/usbd_hid_internal.h b/subsys/usb/device_next/class/usbd_hid_internal.h index d049b0c22a35..dcb747486279 100644 --- a/subsys/usb/device_next/class/usbd_hid_internal.h +++ b/subsys/usb/device_next/class/usbd_hid_internal.h @@ -20,4 +20,6 @@ struct hid_device_driver_api { int (*dev_register)(const struct device *dev, const uint8_t *const rdesc, const uint16_t rsize, const struct hid_device_ops *const ops); + int (*set_in_polling)(const struct device *dev, const unsigned int period_us); + int (*set_out_polling)(const struct device *dev, const unsigned int period_us); }; diff --git a/subsys/usb/device_next/class/usbd_msc.c b/subsys/usb/device_next/class/usbd_msc.c index 07d5d09347f6..6e6c75f671e9 100644 --- a/subsys/usb/device_next/class/usbd_msc.c +++ b/subsys/usb/device_next/class/usbd_msc.c @@ -60,11 +60,8 @@ struct CSW { /* Single instance is likely enough because it can support multiple LUNs */ #define MSC_NUM_INSTANCES CONFIG_USBD_MSC_INSTANCES_COUNT -/* Can be 64 if device is not High-Speed capable */ -#define MSC_BUF_SIZE USBD_MAX_BULK_MPS - UDC_BUF_POOL_DEFINE(msc_ep_pool, - MSC_NUM_INSTANCES * 2, MSC_BUF_SIZE, + MSC_NUM_INSTANCES * 2, USBD_MAX_BULK_MPS, sizeof(struct udc_buf_info), NULL); struct msc_event { @@ -121,9 +118,8 @@ struct msc_bot_ctx { struct scsi_ctx luns[CONFIG_USBD_MSC_LUNS_PER_INSTANCE]; struct CBW cbw; struct CSW csw; - uint8_t scsi_buf[CONFIG_USBD_MSC_SCSI_BUFFER_SIZE]; + uint8_t *scsi_buf; uint32_t transferred_data; - size_t scsi_offset; size_t scsi_bytes; }; @@ -143,6 +139,53 @@ static struct net_buf *msc_buf_alloc(const uint8_t ep) return buf; } +static struct net_buf *msc_buf_alloc_data(const uint8_t ep, uint8_t *data, size_t len) +{ + struct net_buf *buf = NULL; + struct udc_buf_info *bi; + + buf = net_buf_alloc_with_data(&msc_ep_pool, data, len, K_NO_WAIT); + if (buf == NULL) { + return NULL; + } + + if (USB_EP_DIR_IS_OUT(ep)) { + /* Buffer is empty, USB stack will write data from host */ + buf->len = 0; + } + + bi = udc_get_buf_info(buf); + bi->ep = ep; + + return buf; +} + +static size_t msc_next_transfer_length(struct usbd_class_data *const c_data) +{ + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); + struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); + struct scsi_ctx *lun = &ctx->luns[ctx->cbw.bCBWLUN]; + size_t len = scsi_cmd_remaining_data_len(lun); + + len = MIN(CONFIG_USBD_MSC_SCSI_BUFFER_SIZE, len); + + /* Limit transfer to bulk endpoint wMaxPacketSize multiple */ + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + len = ROUND_DOWN(len, 512); + } else { + /* Full-Speed */ + len = ROUND_DOWN(len, 64); + } + + /* Round down to sector size multiple */ + if (lun->sector_size) { + len = ROUND_DOWN(len, lun->sector_size); + } + + return len; +} + static uint8_t msc_get_bulk_in(struct usbd_class_data *const c_data) { struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); @@ -171,10 +214,11 @@ static uint8_t msc_get_bulk_out(struct usbd_class_data *const c_data) return desc->if0_out_ep.bEndpointAddress; } -static void msc_queue_bulk_out_ep(struct usbd_class_data *const c_data) +static void msc_queue_bulk_out_ep(struct usbd_class_data *const c_data, bool data) { struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); struct net_buf *buf; + uint8_t *scsi_buf = ctx->scsi_buf; uint8_t ep; int ret; @@ -185,7 +229,13 @@ static void msc_queue_bulk_out_ep(struct usbd_class_data *const c_data) LOG_DBG("Queuing OUT"); ep = msc_get_bulk_out(c_data); - buf = msc_buf_alloc(ep); + + if (data) { + buf = msc_buf_alloc_data(ep, scsi_buf, msc_next_transfer_length(c_data)); + } else { + buf = msc_buf_alloc(ep); + } + /* The pool is large enough to support all allocations. Failing alloc * indicates either a memory leak or logic error. */ @@ -255,16 +305,24 @@ static void msc_process_read(struct msc_bot_ctx *ctx) struct scsi_ctx *lun = &ctx->luns[ctx->cbw.bCBWLUN]; int bytes_queued = 0; struct net_buf *buf; + uint8_t *scsi_buf = ctx->scsi_buf; uint8_t ep; - size_t len; int ret; /* Fill SCSI Data IN buffer if there is no data available */ if (ctx->scsi_bytes == 0) { - ctx->scsi_bytes = scsi_read_data(lun, ctx->scsi_buf); - ctx->scsi_offset = 0; + size_t len = msc_next_transfer_length(ctx->class_node); + + bytes_queued = scsi_read_data(lun, scsi_buf, len); + } else { + bytes_queued = ctx->scsi_bytes; } + /* All data is submitted in one go. Any potential new data will + * have to be retrieved using scsi_read_data() on next call. + */ + ctx->scsi_bytes = 0; + if (atomic_test_and_set_bit(&ctx->bits, MSC_BULK_IN_QUEUED)) { __ASSERT_NO_MSG(false); LOG_ERR("IN already queued"); @@ -272,33 +330,12 @@ static void msc_process_read(struct msc_bot_ctx *ctx) } ep = msc_get_bulk_in(ctx->class_node); - buf = msc_buf_alloc(ep); + buf = msc_buf_alloc_data(ep, scsi_buf, bytes_queued); /* The pool is large enough to support all allocations. Failing alloc * indicates either a memory leak or logic error. */ __ASSERT_NO_MSG(buf); - while (ctx->scsi_bytes - ctx->scsi_offset > 0) { - len = MIN(ctx->scsi_bytes - ctx->scsi_offset, - MSC_BUF_SIZE - bytes_queued); - if (len == 0) { - /* Either queued as much as possible or there is no more - * SCSI IN data available - */ - break; - } - - net_buf_add_mem(buf, &ctx->scsi_buf[ctx->scsi_offset], len); - bytes_queued += len; - ctx->scsi_offset += len; - - if (ctx->scsi_bytes == ctx->scsi_offset) { - /* SCSI buffer can be reused now */ - ctx->scsi_bytes = scsi_read_data(lun, ctx->scsi_buf); - ctx->scsi_offset = 0; - } - } - /* Either the net buf is full or there is no more SCSI data */ ctx->csw.dCSWDataResidue -= bytes_queued; ret = usbd_ep_enqueue(ctx->class_node, buf); @@ -319,7 +356,6 @@ static void msc_process_cbw(struct msc_bot_ctx *ctx) cb_len = scsi_usb_boot_cmd_len(ctx->cbw.CBWCB, ctx->cbw.bCBWCBLength); data_len = scsi_cmd(lun, ctx->cbw.CBWCB, cb_len, ctx->scsi_buf); ctx->scsi_bytes = data_len; - ctx->scsi_offset = 0; cmd_is_data_read = scsi_cmd_is_data_read(lun); cmd_is_data_write = scsi_cmd_is_data_write(lun); data_len += scsi_cmd_remaining_data_len(lun); @@ -399,46 +435,17 @@ static void msc_process_write(struct msc_bot_ctx *ctx, ctx->transferred_data += len; - while ((len > 0) && (scsi_cmd_remaining_data_len(lun) > 0)) { - /* Copy received data to the end of SCSI buffer */ - tmp = MIN(len, sizeof(ctx->scsi_buf) - ctx->scsi_bytes); - memcpy(&ctx->scsi_buf[ctx->scsi_bytes], buf, tmp); - ctx->scsi_bytes += tmp; - buf += tmp; - len -= tmp; - - /* Pass data to SCSI layer when either all transfer data bytes - * have been received or SCSI buffer is full. - */ - while ((ctx->scsi_bytes >= scsi_cmd_remaining_data_len(lun)) || - (ctx->scsi_bytes == sizeof(ctx->scsi_buf))) { - tmp = scsi_write_data(lun, ctx->scsi_buf, ctx->scsi_bytes); - __ASSERT(tmp <= ctx->scsi_bytes, - "Processed more data than requested"); - if (tmp == 0) { - LOG_WRN("SCSI handler didn't process %d bytes", - ctx->scsi_bytes); - ctx->scsi_bytes = 0; - } else { - LOG_DBG("SCSI processed %d out of %d bytes", - tmp, ctx->scsi_bytes); - } - - ctx->csw.dCSWDataResidue -= tmp; - if (scsi_cmd_remaining_data_len(lun) == 0) { - /* Abandon any leftover data */ - ctx->scsi_bytes = 0; - break; - } - - /* Move remaining data at the start of SCSI buffer. Note - * that the copied length here is zero (and thus no copy - * happens) when underlying sector size is equal to SCSI - * buffer size. - */ - memmove(ctx->scsi_buf, &ctx->scsi_buf[tmp], ctx->scsi_bytes - tmp); - ctx->scsi_bytes -= tmp; + if ((len > 0) && (scsi_cmd_remaining_data_len(lun) > 0)) { + /* Pass data to SCSI layer. */ + tmp = scsi_write_data(lun, buf, len); + __ASSERT(tmp <= len, "Processed more data than requested"); + if (tmp == 0) { + LOG_WRN("SCSI handler didn't process %d bytes", len); + } else { + LOG_DBG("SCSI processed %d out of %d bytes", tmp, len); } + + ctx->csw.dCSWDataResidue -= tmp; } if ((ctx->transferred_data >= ctx->cbw.dCBWDataTransferLength) || @@ -514,7 +521,7 @@ static void msc_handle_bulk_in(struct msc_bot_ctx *ctx, struct scsi_ctx *lun = &ctx->luns[ctx->cbw.bCBWLUN]; ctx->transferred_data += len; - if (ctx->scsi_bytes == 0) { + if (msc_next_transfer_length(ctx->class_node) == 0) { if (ctx->csw.dCSWDataResidue > 0) { /* Case (5) Hi > Di * While we may have sent short packet, device @@ -623,9 +630,11 @@ static void usbd_msc_thread(void *arg1, void *arg2, void *arg3) switch (ctx->state) { case MSC_BBB_EXPECT_CBW: + msc_queue_bulk_out_ep(evt.c_data, false); + break; case MSC_BBB_PROCESS_WRITE: /* Ensure we can accept next OUT packet */ - msc_queue_bulk_out_ep(evt.c_data); + msc_queue_bulk_out_ep(evt.c_data, true); break; default: break; @@ -645,7 +654,7 @@ static void usbd_msc_thread(void *arg1, void *arg2, void *arg3) if (ctx->state == MSC_BBB_PROCESS_READ) { msc_process_read(ctx); } else if (ctx->state == MSC_BBB_PROCESS_WRITE) { - msc_queue_bulk_out_ep(evt.c_data); + msc_queue_bulk_out_ep(evt.c_data, true); } else if (ctx->state == MSC_BBB_SEND_CSW) { msc_send_csw(ctx); } @@ -864,14 +873,17 @@ struct usbd_class_api msc_bot_api = { .init = msc_bot_init, }; -#define DEFINE_MSC_BOT_CLASS_DATA(x, _) \ - static struct msc_bot_ctx msc_bot_ctx_##x = { \ - .desc = &msc_bot_desc_##x, \ - .fs_desc = msc_bot_fs_desc_##x, \ - .hs_desc = msc_bot_hs_desc_##x, \ - }; \ - \ - USBD_DEFINE_CLASS(msc_##x, &msc_bot_api, &msc_bot_ctx_##x, \ +#define DEFINE_MSC_BOT_CLASS_DATA(x, _) \ + UDC_STATIC_BUF_DEFINE(scsi_buf_##x, CONFIG_USBD_MSC_SCSI_BUFFER_SIZE); \ + \ + static struct msc_bot_ctx msc_bot_ctx_##x = { \ + .desc = &msc_bot_desc_##x, \ + .fs_desc = msc_bot_fs_desc_##x, \ + .hs_desc = msc_bot_hs_desc_##x, \ + .scsi_buf = scsi_buf_##x \ + }; \ + \ + USBD_DEFINE_CLASS(msc_##x, &msc_bot_api, &msc_bot_ctx_##x, \ &msc_bot_vregs); LISTIFY(MSC_NUM_INSTANCES, DEFINE_MSC_BOT_DESCRIPTOR, ()) diff --git a/subsys/usb/device_next/class/usbd_msc_scsi.c b/subsys/usb/device_next/class/usbd_msc_scsi.c index 82aa0f50e624..ad88b08af2a3 100644 --- a/subsys/usb/device_next/class/usbd_msc_scsi.c +++ b/subsys/usb/device_next/class/usbd_msc_scsi.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "usbd_msc_scsi.h" @@ -339,6 +340,24 @@ static int update_disk_info(struct scsi_ctx *const ctx) status = -EIO; } + if (!ctx->sector_size) { + status = -EIO; + } else if ((ctx->sector_size % USBD_MAX_BULK_MPS) && + (USBD_MAX_BULK_MPS % ctx->sector_size)) { + /* Zephyr MSC class implementation initially allowed any sector + * size, however doing so requires bouncing which significantly + * impedes throughput. To enable zero-copy and scheduling larger + * transfers, the implementation is now restricted to work only + * with power of two disk sizes. + * + * USB bulk wMaxPacketSize is 64 (Full-Speed), 512 (High-Speed) + * or 1024 (Super-Speed) and most common disk sector sizes are + * either 512 or 4096. Therefore the power of two limitation + * shouldn't have effect on any actual application. + */ + status = -EIO; + } + if (ctx->sector_size > CONFIG_USBD_MSC_SCSI_BUFFER_SIZE) { status = -ENOMEM; } @@ -707,12 +726,11 @@ validate_transfer_length(struct scsi_ctx *ctx, uint32_t lba, uint16_t length) return 0; } -static size_t fill_read_10(struct scsi_ctx *ctx, - uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE]) +static size_t fill_read_10(struct scsi_ctx *ctx, uint8_t *buf, size_t length) { uint32_t sectors; - sectors = MIN(CONFIG_USBD_MSC_SCSI_BUFFER_SIZE, ctx->remaining_data) / ctx->sector_size; + sectors = MIN(length, ctx->remaining_data) / ctx->sector_size; if (disk_access_read(ctx->disk, buf, ctx->lba, sectors) != 0) { /* Terminate transfer */ sectors = 0; @@ -897,15 +915,14 @@ size_t scsi_cmd_remaining_data_len(struct scsi_ctx *ctx) return ctx->remaining_data; } -size_t scsi_read_data(struct scsi_ctx *ctx, - uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE]) +size_t scsi_read_data(struct scsi_ctx *ctx, uint8_t *buf, size_t length) { size_t retrieved = 0; __ASSERT_NO_MSG(ctx->cmd_is_data_read); if ((ctx->remaining_data > 0) && ctx->read_cb) { - retrieved = ctx->read_cb(ctx, buf); + retrieved = ctx->read_cb(ctx, buf, length); } ctx->remaining_data -= retrieved; if (retrieved == 0) { diff --git a/subsys/usb/device_next/class/usbd_msc_scsi.h b/subsys/usb/device_next/class/usbd_msc_scsi.h index 338bb3d5f9bc..ef92899d477a 100644 --- a/subsys/usb/device_next/class/usbd_msc_scsi.h +++ b/subsys/usb/device_next/class/usbd_msc_scsi.h @@ -66,8 +66,7 @@ struct scsi_ctx { const char *vendor; const char *product; const char *revision; - size_t (*read_cb)(struct scsi_ctx *ctx, - uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE]); + size_t (*read_cb)(struct scsi_ctx *ctx, uint8_t *buf, size_t length); size_t (*write_cb)(struct scsi_ctx *ctx, const uint8_t *buf, size_t length); size_t remaining_data; uint32_t lba; @@ -92,8 +91,7 @@ size_t scsi_cmd(struct scsi_ctx *ctx, const uint8_t *cb, int len, bool scsi_cmd_is_data_read(struct scsi_ctx *ctx); bool scsi_cmd_is_data_write(struct scsi_ctx *ctx); size_t scsi_cmd_remaining_data_len(struct scsi_ctx *ctx); -size_t scsi_read_data(struct scsi_ctx *ctx, - uint8_t data_in_buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE]); +size_t scsi_read_data(struct scsi_ctx *ctx, uint8_t *data_in_buf, size_t length); size_t scsi_write_data(struct scsi_ctx *ctx, const uint8_t *buf, size_t length); enum scsi_status_code scsi_cmd_get_status(struct scsi_ctx *ctx); diff --git a/tests/application_development/ram_context_for_isr/Kconfig b/tests/application_development/ram_context_for_isr/Kconfig index 30f2e20a3d12..b4031538b4b9 100644 --- a/tests/application_development/ram_context_for_isr/Kconfig +++ b/tests/application_development/ram_context_for_isr/Kconfig @@ -10,6 +10,9 @@ config TEST_IRQ_NUM default 14 if GIC default 22 if SOC_SERIES_DA1469X default 18 if SOC_SERIES_STM32C0X + default 1 if (SOC_SERIES_NPCX9 || SOC_SERIES_NPCX7 || SOC_SERIES_NPCK3) + default 29 if SOC_K32L2B31A + default 28 if SOC_SERIES_NRF54LX default 0 help IRQ number to use for testing purposes. This should be an @@ -20,6 +23,8 @@ config TEST_IRQ_NUM - GIC platforms: 14 (available test SGI - Software Generated Interrupt) - DA1469X series: 22 (available test IRQ) - STM32C0X series: 18 (available test IRQ) + - NPCX9, NPCX7, NPCK3 series: 1 (unused IRQ not mapped to MIWU groups) + - K32L2B31A: 29 (available test IRQ) - Other platforms: 0 (magic config value to select the last IRQ: NUM_IRQS - 1) config TEST_IRQ_PRIO diff --git a/tests/application_development/ram_context_for_isr/boards/nrf54l05dk_nrf54l05_cpuapp.conf b/tests/application_development/ram_context_for_isr/boards/nrf54l05dk_nrf54l05_cpuapp.conf new file mode 100644 index 000000000000..963ba83325a4 --- /dev/null +++ b/tests/application_development/ram_context_for_isr/boards/nrf54l05dk_nrf54l05_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_CRACEN_LIB_KMU=n diff --git a/tests/application_development/ram_context_for_isr/boards/nrf54l15dk_nrf54l10_cpuapp.conf b/tests/application_development/ram_context_for_isr/boards/nrf54l15dk_nrf54l10_cpuapp.conf new file mode 100644 index 000000000000..963ba83325a4 --- /dev/null +++ b/tests/application_development/ram_context_for_isr/boards/nrf54l15dk_nrf54l10_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_CRACEN_LIB_KMU=n diff --git a/tests/application_development/ram_context_for_isr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/tests/application_development/ram_context_for_isr/boards/nrf54l15dk_nrf54l15_cpuapp.conf new file mode 100644 index 000000000000..963ba83325a4 --- /dev/null +++ b/tests/application_development/ram_context_for_isr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_CRACEN_LIB_KMU=n diff --git a/tests/application_development/ram_context_for_isr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/tests/application_development/ram_context_for_isr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 000000000000..963ba83325a4 --- /dev/null +++ b/tests/application_development/ram_context_for_isr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_CRACEN_LIB_KMU=n diff --git a/tests/application_development/ram_context_for_isr/boards/nrf54lv10dk_nrf54lv10a_cpuapp.conf b/tests/application_development/ram_context_for_isr/boards/nrf54lv10dk_nrf54lv10a_cpuapp.conf new file mode 100644 index 000000000000..963ba83325a4 --- /dev/null +++ b/tests/application_development/ram_context_for_isr/boards/nrf54lv10dk_nrf54lv10a_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_CRACEN_LIB_KMU=n diff --git a/tests/application_development/ram_context_for_isr/boards/nrf7120pdk_nrf7120_cpuapp.conf b/tests/application_development/ram_context_for_isr/boards/nrf7120pdk_nrf7120_cpuapp.conf new file mode 100644 index 000000000000..963ba83325a4 --- /dev/null +++ b/tests/application_development/ram_context_for_isr/boards/nrf7120pdk_nrf7120_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_CRACEN_LIB_KMU=n diff --git a/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 000000000000..e12e413d9e5a --- /dev/null +++ b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_POWER_DOMAIN=n diff --git a/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 000000000000..e12e413d9e5a --- /dev/null +++ b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_POWER_DOMAIN=n diff --git a/tests/arch/common/gen_isr_table/src/main.c b/tests/arch/common/gen_isr_table/src/main.c index e716f0ddf4b6..ed764e05b4bf 100644 --- a/tests/arch/common/gen_isr_table/src/main.c +++ b/tests/arch/common/gen_isr_table/src/main.c @@ -42,6 +42,11 @@ extern const uintptr_t _irq_vector_table[]; #define ISR3_OFFSET 15 #define ISR5_OFFSET 16 #define TRIG_CHECK_SIZE 17 +#elif defined(CONFIG_SOC_NRF9280_CPUPPR) +#define ISR1_OFFSET 14 +#define ISR3_OFFSET 15 +#define ISR5_OFFSET 16 +#define TRIG_CHECK_SIZE 17 #else #error "Target not supported" #endif diff --git a/tests/bluetooth/controller/ctrl_api/testcase.yaml b/tests/bluetooth/controller/ctrl_api/testcase.yaml index 19bf6c9ab490..21f178bf9b2b 100644 --- a/tests/bluetooth/controller/ctrl_api/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_api/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_api.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_chmu/testcase.yaml b/tests/bluetooth/controller/ctrl_chmu/testcase.yaml index f7e8068d60ec..9c3ee6264335 100644 --- a/tests/bluetooth/controller/ctrl_chmu/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_chmu/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_chmu.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_cis_create/testcase.yaml b/tests/bluetooth/controller/ctrl_cis_create/testcase.yaml index 99612a89bc31..2371d7063eb7 100644 --- a/tests/bluetooth/controller/ctrl_cis_create/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_cis_create/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_cis_create.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_cis_terminate/testcase.yaml b/tests/bluetooth/controller/ctrl_cis_terminate/testcase.yaml index 956172a89b20..a98229ba45f3 100644 --- a/tests/bluetooth/controller/ctrl_cis_terminate/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_cis_terminate/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_cis_terminate.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_collision/testcase.yaml b/tests/bluetooth/controller/ctrl_collision/testcase.yaml index 6086a9a4ebc8..daa8f3bc6c3d 100644 --- a/tests/bluetooth/controller/ctrl_collision/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_collision/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_collision.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_conn_update/testcase.yaml b/tests/bluetooth/controller/ctrl_conn_update/testcase.yaml index 5b0bda4b9088..fc4ecb0b647d 100644 --- a/tests/bluetooth/controller/ctrl_conn_update/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_conn_update/testcase.yaml @@ -7,11 +7,18 @@ common: tests: bluetooth.controller.ctrl_conn_update.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_conn_update.apm_test: type: unit - extra_args: CONF_FILE=prj_apm.conf + extra_args: + - CONF_FILE=prj_apm.conf + - SNIPPET="bt-ll-sw-split" + bluetooth.controller.ctrl_conn_update.no_param_req_test: type: unit - extra_args: CONF_FILE=prj_no_param_req.conf + extra_args: + - CONF_FILE=prj_no_param_req.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_cte_req/testcase.yaml b/tests/bluetooth/controller/ctrl_cte_req/testcase.yaml index fd6ff51118d9..c6288aecc433 100644 --- a/tests/bluetooth/controller/ctrl_cte_req/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_cte_req/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_cte_req.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_data_length_update/testcase.yaml b/tests/bluetooth/controller/ctrl_data_length_update/testcase.yaml index 9778af435b4a..c7d1174e12bf 100644 --- a/tests/bluetooth/controller/ctrl_data_length_update/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_data_length_update/testcase.yaml @@ -6,11 +6,17 @@ common: tests: bluetooth.controller.ctrl_data_length_update.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_data_length_update.test_nocodedphy: type: unit - extra_args: CONF_FILE=prj_nocoded.conf + extra_args: + - CONF_FILE=prj_nocoded.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_data_length_update.test_nophy: type: unit - extra_args: CONF_FILE=prj_nophy.conf + extra_args: + - CONF_FILE=prj_nophy.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_encrypt/testcase.yaml b/tests/bluetooth/controller/ctrl_encrypt/testcase.yaml index d5bb2cb8b110..86dd5bfe4d30 100644 --- a/tests/bluetooth/controller/ctrl_encrypt/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_encrypt/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_encrypt.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_feature_exchange/testcase.yaml b/tests/bluetooth/controller/ctrl_feature_exchange/testcase.yaml index 257542f36120..087e49575ff7 100644 --- a/tests/bluetooth/controller/ctrl_feature_exchange/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_feature_exchange/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_feature_exchange.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_hci/testcase.yaml b/tests/bluetooth/controller/ctrl_hci/testcase.yaml index d7f7ce7168d1..e0735bae6962 100644 --- a/tests/bluetooth/controller/ctrl_hci/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_hci/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_hci.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_invalid/testcase.yaml b/tests/bluetooth/controller/ctrl_invalid/testcase.yaml index 2d1741931e37..cee54e6b09ed 100644 --- a/tests/bluetooth/controller/ctrl_invalid/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_invalid/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_invalid.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_le_ping/testcase.yaml b/tests/bluetooth/controller/ctrl_le_ping/testcase.yaml index b6a77528f32d..54178905da17 100644 --- a/tests/bluetooth/controller/ctrl_le_ping/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_le_ping/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_le_ping.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_min_used_chans/testcase.yaml b/tests/bluetooth/controller/ctrl_min_used_chans/testcase.yaml index 0991b0cdd43c..a9445cbf8c4d 100644 --- a/tests/bluetooth/controller/ctrl_min_used_chans/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_min_used_chans/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_min_used_chans.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_phy_update/testcase.yaml b/tests/bluetooth/controller/ctrl_phy_update/testcase.yaml index 1d7da169f1d8..d5c49d587a8f 100644 --- a/tests/bluetooth/controller/ctrl_phy_update/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_phy_update/testcase.yaml @@ -6,6 +6,10 @@ common: tests: bluetooth.controller.ctrl_phy_update.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_phy_update.test_reduced_buf: type: unit - extra_args: CONF_FILE=prj_rx_cnt.conf + extra_args: + - CONF_FILE=prj_rx_cnt.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_sca_update/testcase.yaml b/tests/bluetooth/controller/ctrl_sca_update/testcase.yaml index cbf63aa1b575..cbc3c3faf720 100644 --- a/tests/bluetooth/controller/ctrl_sca_update/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_sca_update/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_sca_update.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_sw_privacy/testcase.yaml b/tests/bluetooth/controller/ctrl_sw_privacy/testcase.yaml index 778606d69549..ac5dd6e957eb 100644 --- a/tests/bluetooth/controller/ctrl_sw_privacy/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_sw_privacy/testcase.yaml @@ -4,3 +4,5 @@ common: tests: bluetooth.ctrl_sw_privacy.test: platform_allow: nrf52_bsim + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_terminate/testcase.yaml b/tests/bluetooth/controller/ctrl_terminate/testcase.yaml index cbe639401ea3..6b1409e9653e 100644 --- a/tests/bluetooth/controller/ctrl_terminate/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_terminate/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_terminate.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/testcase.yaml b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/testcase.yaml index 614eb7fe94c0..363986bd3d35 100644 --- a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/testcase.yaml @@ -6,23 +6,35 @@ common: tests: bluetooth.controller.ctrl_tx_buffer_alloc.test_0_per_conn: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_1_per_conn: type: unit - extra_args: CONF_FILE=prj_1.conf + extra_args: + - CONF_FILE=prj_1.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_2_per_conn: type: unit - extra_args: CONF_FILE=prj_2.conf + extra_args: + - CONF_FILE=prj_2.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_3_per_conn: type: unit - extra_args: CONF_FILE=prj_3.conf + extra_args: + - CONF_FILE=prj_3.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_max_per_conn_alloc: type: unit - extra_args: CONF_FILE=prj_max.conf + extra_args: + - CONF_FILE=prj_max.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_max_common_alloc: type: unit - extra_args: CONF_FILE=prj_max_common.conf + extra_args: + - CONF_FILE=prj_max_common.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_tx_queue/testcase.yaml b/tests/bluetooth/controller/ctrl_tx_queue/testcase.yaml index 295ad891a630..282b620b317a 100644 --- a/tests/bluetooth/controller/ctrl_tx_queue/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_tx_queue/testcase.yaml @@ -5,3 +5,5 @@ common: tests: bluetooth.ctrl_tx_queue.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_unsupported/testcase.yaml b/tests/bluetooth/controller/ctrl_unsupported/testcase.yaml index 28aba1a752a8..48b18af93536 100644 --- a/tests/bluetooth/controller/ctrl_unsupported/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_unsupported/testcase.yaml @@ -6,7 +6,11 @@ common: tests: bluetooth.controller.ctrl_unsupported.default.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_unsupported.test: type: unit - extra_args: CONF_FILE=prj_unsupported.conf + extra_args: + - CONF_FILE=prj_unsupported.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_user_ext/testcase.yaml b/tests/bluetooth/controller/ctrl_user_ext/testcase.yaml index af319a7a7191..be963df24a8a 100644 --- a/tests/bluetooth/controller/ctrl_user_ext/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_user_ext/testcase.yaml @@ -4,3 +4,5 @@ common: tests: bluetooth.ctrl_user_ext.test: platform_allow: nrf52_bsim + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_version/testcase.yaml b/tests/bluetooth/controller/ctrl_version/testcase.yaml index 6badcbc72547..5df86b9bca9f 100644 --- a/tests/bluetooth/controller/ctrl_version/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_version/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_version.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connection_cte_req/testcase.yaml b/tests/bluetooth/df/connection_cte_req/testcase.yaml index 768aba4a51f5..fbfe4b0d9a1a 100644 --- a/tests/bluetooth/df/connection_cte_req/testcase.yaml +++ b/tests/bluetooth/df/connection_cte_req/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.conection_cte_req: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connection_cte_tx_params/testcase.yaml b/tests/bluetooth/df/connection_cte_tx_params/testcase.yaml index 38a23b0950e3..a9986c5b0e53 100644 --- a/tests/bluetooth/df/connection_cte_tx_params/testcase.yaml +++ b/tests/bluetooth/df/connection_cte_tx_params/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.conection_cte_tx_params: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connectionless_cte_chains/testcase.yaml b/tests/bluetooth/df/connectionless_cte_chains/testcase.yaml index 6aa5bb0f0c1c..844a7bbb524e 100644 --- a/tests/bluetooth/df/connectionless_cte_chains/testcase.yaml +++ b/tests/bluetooth/df/connectionless_cte_chains/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.connectionless_cte_chains: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connectionless_cte_rx/testcase.yaml b/tests/bluetooth/df/connectionless_cte_rx/testcase.yaml index f839b1910eb2..c8f08a908436 100644 --- a/tests/bluetooth/df/connectionless_cte_rx/testcase.yaml +++ b/tests/bluetooth/df/connectionless_cte_rx/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.connectionless_cte_rx: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connectionless_cte_tx/testcase.yaml b/tests/bluetooth/df/connectionless_cte_tx/testcase.yaml index 77d651d0cbc2..491cc0e7e599 100644 --- a/tests/bluetooth/df/connectionless_cte_tx/testcase.yaml +++ b/tests/bluetooth/df/connectionless_cte_tx/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.connectionless_cte_tx: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/host/id/mocks/adv.c b/tests/bluetooth/host/id/mocks/adv.c index 2c2d4f3f3c7a..a22123dea3da 100644 --- a/tests/bluetooth/host/id/mocks/adv.c +++ b/tests/bluetooth/host/id/mocks/adv.c @@ -15,3 +15,4 @@ DEFINE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable_legacy, struct bt_le_ext_adv *, DEFINE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable_ext, struct bt_le_ext_adv *, bool, const struct bt_le_ext_adv_start_param *); DEFINE_FAKE_VOID_FUNC(bt_le_ext_adv_foreach, bt_le_ext_adv_foreach_cb, void *); +DEFINE_FAKE_VALUE_FUNC(struct bt_le_ext_adv *, bt_adv_lookup_by_id, uint8_t); diff --git a/tests/bluetooth/host/id/mocks/adv.h b/tests/bluetooth/host/id/mocks/adv.h index bfb744001596..1602ddf47185 100644 --- a/tests/bluetooth/host/id/mocks/adv.h +++ b/tests/bluetooth/host/id/mocks/adv.h @@ -18,7 +18,8 @@ typedef void (*bt_le_ext_adv_foreach_cb)(struct bt_le_ext_adv *adv, void *data); FAKE(bt_le_adv_lookup_legacy) \ FAKE(bt_le_ext_adv_get_index) \ FAKE(bt_le_adv_set_enable_ext) \ - FAKE(bt_le_ext_adv_foreach) + FAKE(bt_le_ext_adv_foreach) \ + FAKE(bt_adv_lookup_by_id) DECLARE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable, struct bt_le_ext_adv *, bool); DECLARE_FAKE_VALUE_FUNC(struct bt_le_ext_adv *, bt_le_adv_lookup_legacy); @@ -27,3 +28,4 @@ DECLARE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable_legacy, struct bt_le_ext_adv * DECLARE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable_ext, struct bt_le_ext_adv *, bool, const struct bt_le_ext_adv_start_param *); DECLARE_FAKE_VOID_FUNC(bt_le_ext_adv_foreach, bt_le_ext_adv_foreach_cb, void *); +DECLARE_FAKE_VALUE_FUNC(struct bt_le_ext_adv *, bt_adv_lookup_by_id, uint8_t); diff --git a/tests/bluetooth/host/id/mocks/keys.c b/tests/bluetooth/host/id/mocks/keys.c index f885ab875c0f..61f73569c469 100644 --- a/tests/bluetooth/host/id/mocks/keys.c +++ b/tests/bluetooth/host/id/mocks/keys.c @@ -10,3 +10,4 @@ DEFINE_FAKE_VALUE_FUNC(struct bt_keys *, bt_keys_find_irk, uint8_t, const bt_addr_le_t *); DEFINE_FAKE_VOID_FUNC(bt_keys_foreach_type, enum bt_keys_type, bt_keys_foreach_type_cb, void *); +DEFINE_FAKE_VALUE_FUNC(struct bt_keys *, bt_keys_get_addr, uint8_t, const bt_addr_le_t *); diff --git a/tests/bluetooth/host/id/mocks/keys.h b/tests/bluetooth/host/id/mocks/keys.h index b6901e315ab9..1912472b78de 100644 --- a/tests/bluetooth/host/id/mocks/keys.h +++ b/tests/bluetooth/host/id/mocks/keys.h @@ -15,7 +15,9 @@ typedef void (*bt_keys_foreach_type_cb)(struct bt_keys *keys, void *data); /* List of fakes used by this unit tester */ #define KEYS_FFF_FAKES_LIST(FAKE) \ FAKE(bt_keys_find_irk) \ - FAKE(bt_keys_foreach_type) + FAKE(bt_keys_foreach_type) \ + FAKE(bt_keys_get_addr) DECLARE_FAKE_VALUE_FUNC(struct bt_keys *, bt_keys_find_irk, uint8_t, const bt_addr_le_t *); DECLARE_FAKE_VOID_FUNC(bt_keys_foreach_type, enum bt_keys_type, bt_keys_foreach_type_cb, void *); +DECLARE_FAKE_VALUE_FUNC(struct bt_keys *, bt_keys_get_addr, uint8_t, const bt_addr_le_t *); diff --git a/tests/bluetooth/init/prj_ctlr.conf b/tests/bluetooth/init/prj_ctlr.conf index b311a76b1cde..c733ef4ad3fc 100644 --- a/tests/bluetooth/init/prj_ctlr.conf +++ b/tests/bluetooth/init/prj_ctlr.conf @@ -8,6 +8,7 @@ CONFIG_BT_SMP_SC_ONLY=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y CONFIG_BT_GATT_CLIENT=y CONFIG_BT_CLASSIC=n +CONFIG_BT_CTLR_ASSERT_DEBUG=n CONFIG_FLASH=y CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER=y CONFIG_ZTEST=y diff --git a/tests/bluetooth/init/prj_ctlr_dbg.conf b/tests/bluetooth/init/prj_ctlr_dbg.conf index cc6f478b66b6..956c562c5aa0 100644 --- a/tests/bluetooth/init/prj_ctlr_dbg.conf +++ b/tests/bluetooth/init/prj_ctlr_dbg.conf @@ -31,6 +31,7 @@ CONFIG_BT_CTLR_SCAN_REQ_RSSI=y CONFIG_BT_CTLR_SCAN_INDICATION=y CONFIG_BT_CTLR_OPTIMIZE_FOR_SPEED=y CONFIG_BT_CTLR_PROFILE_ISR=y +CONFIG_BT_CTLR_ASSERT_DEBUG=y CONFIG_BT_CTLR_DEBUG_PINS=y CONFIG_BT_CTLR_TEST=y CONFIG_BT_HCI_VS=y diff --git a/tests/bluetooth/init/testcase.yaml b/tests/bluetooth/init/testcase.yaml index dd44257e0128..a5cc40cd39e7 100644 --- a/tests/bluetooth/init/testcase.yaml +++ b/tests/bluetooth/init/testcase.yaml @@ -74,7 +74,9 @@ tests: extra_args: CONF_FILE=prj_9.conf platform_allow: qemu_cortex_m3 bluetooth.init.test_ctlr: - extra_args: CONF_FILE=prj_ctlr.conf + extra_args: + - CONF_FILE=prj_ctlr.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -86,7 +88,9 @@ tests: - nrf51dk/nrf51822 - rv32m1_vega/openisa_rv32m1/ri5cy bluetooth.init.test_ctlr_4_0: - extra_args: CONF_FILE=prj_ctlr_4_0.conf + extra_args: + - CONF_FILE=prj_ctlr_4_0.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -95,7 +99,9 @@ tests: - nrf52dk/nrf52832 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_4_0_dbg: - extra_args: CONF_FILE=prj_ctlr_4_0_dbg.conf + extra_args: + - CONF_FILE=prj_ctlr_4_0_dbg.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -104,7 +110,9 @@ tests: - nrf52dk/nrf52832 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_tiny: - extra_args: CONF_FILE=prj_ctlr_tiny.conf + extra_args: + - CONF_FILE=prj_ctlr_tiny.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -116,6 +124,7 @@ tests: extra_args: - CONF_FILE=prj_ctlr_dbg.conf - DTC_OVERLAY_FILE=pa_lna.overlay + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -126,6 +135,7 @@ tests: extra_args: - CONF_FILE=prj_ctlr_5_x_dbg.conf - DTC_OVERLAY_FILE=pa_lna.overlay + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -137,6 +147,7 @@ tests: - CONF_FILE=prj_ctlr.conf - CONFIG_BT_CTLR_ADVANCED_FEATURES=y - CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER=y + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf52840dk/nrf52840 @@ -146,13 +157,16 @@ tests: bluetooth.init.test_ctlr_ticker: extra_args: - CONF_FILE=prj_ctlr_ticker.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 integration_platforms: - nrf52dk/nrf52832 bluetooth.init.test_ctlr_broadcaster: - extra_args: CONF_FILE=prj_ctlr_broadcaster.conf + extra_args: + - CONF_FILE=prj_ctlr_broadcaster.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -161,7 +175,9 @@ tests: integration_platforms: - nrf52dk/nrf52832 bluetooth.init.test_ctlr_peripheral: - extra_args: CONF_FILE=prj_ctlr_peripheral.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -170,7 +186,9 @@ tests: integration_platforms: - nrf52dk/nrf52832 bluetooth.init.test_ctlr_peripheral_priv: - extra_args: CONF_FILE=prj_ctlr_peripheral_priv.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral_priv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -179,7 +197,9 @@ tests: integration_platforms: - nrf52840dk/nrf52840 bluetooth.init.test_ctlr_observer: - extra_args: CONF_FILE=prj_ctlr_observer.conf + extra_args: + - CONF_FILE=prj_ctlr_observer.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -188,7 +208,9 @@ tests: integration_platforms: - nrf52dk/nrf52832 bluetooth.init.test_ctlr_central: - extra_args: CONF_FILE=prj_ctlr_central.conf + extra_args: + - CONF_FILE=prj_ctlr_central.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -198,7 +220,9 @@ tests: - nrf52dk/nrf52832 - rv32m1_vega/openisa_rv32m1/ri5cy bluetooth.init.test_ctlr_central_priv: - extra_args: CONF_FILE=prj_ctlr_central_priv.conf + extra_args: + - CONF_FILE=prj_ctlr_central_priv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -208,7 +232,9 @@ tests: - nrf52dk/nrf52832 - rv32m1_vega/openisa_rv32m1/ri5cy bluetooth.init.test_ctlr_broadcaster_ext: - extra_args: CONF_FILE=prj_ctlr_broadcaster_ext.conf + extra_args: + - CONF_FILE=prj_ctlr_broadcaster_ext.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -217,7 +243,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_peripheral_ext: - extra_args: CONF_FILE=prj_ctlr_peripheral_ext.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral_ext.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -226,7 +254,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_peripheral_ext_priv: - extra_args: CONF_FILE=prj_ctlr_peripheral_ext_priv.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral_ext_priv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -235,7 +265,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_oberver_ext: - extra_args: CONF_FILE=prj_ctlr_observer_ext.conf + extra_args: + - CONF_FILE=prj_ctlr_observer_ext.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -244,7 +276,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_central_ext: - extra_args: CONF_FILE=prj_ctlr_central_ext.conf + extra_args: + - CONF_FILE=prj_ctlr_central_ext.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -253,7 +287,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_central_ext_priv: - extra_args: CONF_FILE=prj_ctlr_central_ext_priv.conf + extra_args: + - CONF_FILE=prj_ctlr_central_ext_priv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -262,7 +298,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_adv: - extra_args: CONF_FILE=prj_ctlr_per_adv.conf + extra_args: + - CONF_FILE=prj_ctlr_per_adv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -271,7 +309,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_adv_no_adi: - extra_args: CONF_FILE=prj_ctlr_per_adv_no_adi.conf + extra_args: + - CONF_FILE=prj_ctlr_per_adv_no_adi.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -280,7 +320,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_sync: - extra_args: CONF_FILE=prj_ctlr_per_sync.conf + extra_args: + - CONF_FILE=prj_ctlr_per_sync.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -289,7 +331,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_sync_no_adi: - extra_args: CONF_FILE=prj_ctlr_per_sync_no_adi.conf + extra_args: + - CONF_FILE=prj_ctlr_per_sync_no_adi.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -298,7 +342,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_sync_no_filter: - extra_args: CONF_FILE=prj_ctlr_per_sync_no_filter.conf + extra_args: + - CONF_FILE=prj_ctlr_per_sync_no_filter.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -307,7 +353,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_peripheral_iso: - extra_args: CONF_FILE=prj_ctlr_peripheral_iso.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral_iso.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -316,7 +364,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_central_iso: - extra_args: CONF_FILE=prj_ctlr_central_iso.conf + extra_args: + - CONF_FILE=prj_ctlr_central_iso.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -335,7 +385,9 @@ tests: - DTC_OVERLAY_FILE=h5.overlay platform_allow: qemu_cortex_m3 bluetooth.init.test_llcp: - extra_args: CONF_FILE=prj_llcp.conf + extra_args: + - CONF_FILE=prj_llcp.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -347,6 +399,7 @@ tests: extra_args: - CONF_FILE=prj_ctlr.conf - CONFIG_BT_RECV_WORKQ_BT=y + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 bluetooth.init.test_host_6_x: diff --git a/tests/bluetooth/mesh_shell/boards/qemu_x86.conf b/tests/bluetooth/mesh_shell/boards/qemu_x86.conf new file mode 100644 index 000000000000..bfb57193b782 --- /dev/null +++ b/tests/bluetooth/mesh_shell/boards/qemu_x86.conf @@ -0,0 +1,6 @@ +# nrf_security only supports Cortex-M via PSA crypto libraries. +# Enforcing usage of built-in Mbed TLS for native simulator. +CONFIG_NRF_SECURITY=n +CONFIG_MBEDTLS_ENABLE_HEAP=n +CONFIG_TRUSTED_STORAGE=n +CONFIG_SECURE_STORAGE=y diff --git a/tests/bluetooth/mesh_shell/prj.conf b/tests/bluetooth/mesh_shell/prj.conf index 2af600295680..aab2745d359f 100644 --- a/tests/bluetooth/mesh_shell/prj.conf +++ b/tests/bluetooth/mesh_shell/prj.conf @@ -14,7 +14,7 @@ CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y CONFIG_BT=y CONFIG_BT_OBSERVER=y diff --git a/tests/bluetooth/shell/audio.conf b/tests/bluetooth/shell/audio.conf index bae871f97cb2..45236a49afae 100644 --- a/tests/bluetooth/shell/audio.conf +++ b/tests/bluetooth/shell/audio.conf @@ -22,7 +22,7 @@ CONFIG_BT_GATT_AUTO_DISCOVER_CCC=y CONFIG_BT_GATT_AUTO_UPDATE_MTU=y CONFIG_BT_L2CAP_ECRED=y CONFIG_BT_SIGNING=y -CONFIG_BT_FIXED_PASSKEY=y +CONFIG_BT_APP_PASSKEY=y CONFIG_BT_ATT_PREPARE_COUNT=5 CONFIG_BT_SHELL=y CONFIG_BT_DEVICE_NAME="audio test shell" diff --git a/tests/bluetooth/shell/log.conf b/tests/bluetooth/shell/log.conf index 7a9aa9b8680f..2da43186e19f 100644 --- a/tests/bluetooth/shell/log.conf +++ b/tests/bluetooth/shell/log.conf @@ -9,7 +9,7 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT_PRIVACY=y CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y -CONFIG_BT_FIXED_PASSKEY=y +CONFIG_BT_APP_PASSKEY=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y diff --git a/tests/bluetooth/shell/prj.conf b/tests/bluetooth/shell/prj.conf index 510d0988262c..2c84d55bd69a 100644 --- a/tests/bluetooth/shell/prj.conf +++ b/tests/bluetooth/shell/prj.conf @@ -11,7 +11,7 @@ CONFIG_BT_PRIVACY=y CONFIG_BT_SMP=y CONFIG_BT_PASSKEY_KEYPRESS=y CONFIG_BT_SIGNING=y -CONFIG_BT_FIXED_PASSKEY=y +CONFIG_BT_APP_PASSKEY=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y diff --git a/tests/bluetooth/tester/Kconfig.sysbuild b/tests/bluetooth/tester/Kconfig.sysbuild index 69e4d5a97fbe..e14a6e1aa8e0 100644 --- a/tests/bluetooth/tester/Kconfig.sysbuild +++ b/tests/bluetooth/tester/Kconfig.sysbuild @@ -5,6 +5,7 @@ source "share/sysbuild/Kconfig" config NET_CORE_BOARD string + default "nrf54h20dk/nrf54h20/cpurad" if "$(BOARD)" = "nrf54h20dk" default "nrf5340dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340dk" default "nrf5340_audio_dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340_audio_dk" default "nrf5340bsim/nrf5340/cpunet" if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" diff --git a/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.conf index 5bb1c4d82846..0f16f6ea7b4c 100644 --- a/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -22,3 +22,9 @@ CONFIG_LOG_DEFAULT_LEVEL=3 CONFIG_BTTESTER_LOG_LEVEL_DBG=y CONFIG_UART_INTERRUPT_DRIVEN=y + +# Enable PSA RNG +CONFIG_PSA_CRYPTO_DRIVER_OBERON=n +CONFIG_PSA_SSF_CRYPTO_CLIENT=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_NRF_SECURITY=y diff --git a/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index e6d4f675f57a..4f9de686b7e5 100644 --- a/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -12,3 +12,17 @@ status = "okay"; hw-flow-control; }; + +// Enable PSA RNG +/ { + chosen { + zephyr,entropy = &psa_rng; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; + + /delete-node/ prng; +}; diff --git a/tests/bluetooth/tester/overlay-le-audio.conf b/tests/bluetooth/tester/overlay-le-audio.conf index 30f609b9ace5..f6fb0e9c4094 100644 --- a/tests/bluetooth/tester/overlay-le-audio.conf +++ b/tests/bluetooth/tester/overlay-le-audio.conf @@ -130,6 +130,8 @@ CONFIG_BT_HAS_CLIENT=y # CSIS CONFIG_BT_CSIP_SET_MEMBER=y CONFIG_BT_CSIP_SET_MEMBER_ENC_SIRK_SUPPORT=y +CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE=y +CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE=y # CSIP CONFIG_BT_CSIP_SET_COORDINATOR=y diff --git a/tests/bluetooth/tester/src/audio/btp/btp_csis.h b/tests/bluetooth/tester/src/audio/btp/btp_csis.h index f007a6a938a2..3f28e942414d 100644 --- a/tests/bluetooth/tester/src/audio/btp/btp_csis.h +++ b/tests/bluetooth/tester/src/audio/btp/btp_csis.h @@ -12,6 +12,10 @@ #include /* CSIS commands */ +#define BTP_CSIS_SIRK_TYPE_PLAINTEXT 0x00 +#define BTP_CSIS_SIRK_TYPE_ENCRYPTED 0x01 +#define BTP_CSIS_SIRK_TYPE_OOB_ONLY 0x02 + #define BTP_CSIS_READ_SUPPORTED_COMMANDS 0x01 struct btp_csis_read_supported_commands_rp { uint8_t data[0]; @@ -33,7 +37,18 @@ struct btp_csis_get_member_rsi_rp { uint8_t rsi[BT_CSIP_RSI_SIZE]; } __packed; -#define BTP_CSIS_ENC_SIRK_TYPE 0x04 -struct btp_csis_sirk_type_cmd { - uint8_t encrypted; +#define BTP_CSIS_SET_SIRK_TYPE 0x04 +struct btp_csis_sirk_set_type_cmd { + uint8_t type; +} __packed; + +#define BTP_CSIS_SET_SIRK 0x05 +struct btp_csis_set_sirk_cmd { + uint8_t sirk[BT_CSIP_SIRK_SIZE]; +} __packed; + +#define BTP_CSIS_SET_SET_SIZE 0x06 +struct btp_csis_set_set_size_cmd { + uint8_t set_size; + uint8_t rank; } __packed; diff --git a/tests/bluetooth/tester/src/audio/btp/btp_vcs.h b/tests/bluetooth/tester/src/audio/btp/btp_vcs.h index 6f31afe020c8..069b562c03d4 100644 --- a/tests/bluetooth/tester/src/audio/btp/btp_vcs.h +++ b/tests/bluetooth/tester/src/audio/btp/btp_vcs.h @@ -8,6 +8,8 @@ #include +#define BTP_VCS_REGISTER_FLAG_MUTED BIT(0) + #define BTP_VCS_READ_SUPPORTED_COMMANDS 0x01 struct btp_vcs_read_supported_commands_rp { uint8_t data[0]; @@ -22,3 +24,10 @@ struct btp_vcs_set_vol_cmd { #define BTP_VCS_VOL_DOWN 0x04 #define BTP_VCS_MUTE 0x05 #define BTP_VCS_UNMUTE 0x06 + +#define BTP_VCS_REGISTER 0x07 +struct btp_vcs_register_cmd { + uint8_t step; + uint8_t flags; + uint8_t volume; +} __packed; diff --git a/tests/bluetooth/tester/src/audio/btp_bap_broadcast.c b/tests/bluetooth/tester/src/audio/btp_bap_broadcast.c index e26046d2b083..3733ab36440a 100644 --- a/tests/bluetooth/tester/src/audio/btp_bap_broadcast.c +++ b/tests/bluetooth/tester/src/audio/btp_bap_broadcast.c @@ -1162,6 +1162,8 @@ static int pa_sync_req_cb(struct bt_conn *conn, bt_addr_le_copy(&broadcaster->address, &recv_state->addr); } + broadcast_source_to_sync = broadcaster; + broadcaster->sink_recv_state = recv_state; btp_send_pas_sync_req_ev(conn, recv_state->src_id, recv_state->adv_sid, @@ -1380,20 +1382,6 @@ uint8_t btp_bap_broadcast_sink_sync(const void *cmd, uint16_t cmd_len, void *rsp LOG_DBG(""); - broadcaster = remote_broadcaster_find(&cp->address, broadcast_id); - if (broadcaster == NULL) { - broadcaster = remote_broadcaster_alloc(); - if (broadcaster == NULL) { - LOG_ERR("Failed to allocate broadcast source"); - return BTP_STATUS_FAILED; - } - - broadcaster->broadcast_id = broadcast_id; - bt_addr_le_copy(&broadcaster->address, &cp->address); - } - - broadcast_source_to_sync = broadcaster; - if (IS_ENABLED(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER) && cp->past_avail) { /* The Broadcast Assistant supports PAST transfer, and it has found * a Broadcaster for us. Let's sync to the Broadcaster PA with the PAST. @@ -1421,7 +1409,22 @@ uint8_t btp_bap_broadcast_sink_sync(const void *cmd, uint16_t cmd_len, void *rsp create_params.sid = cp->advertiser_sid; create_params.skip = cp->skip; create_params.timeout = cp->sync_timeout; + err = tester_gap_padv_create_sync(&create_params); + + broadcaster = remote_broadcaster_find(&cp->address, broadcast_id); + if (broadcaster == NULL) { + broadcaster = remote_broadcaster_alloc(); + if (broadcaster == NULL) { + LOG_ERR("Failed to allocate broadcast source"); + return BTP_STATUS_FAILED; + } + + broadcaster->broadcast_id = broadcast_id; + bt_addr_le_copy(&broadcaster->address, &cp->address); + } + + broadcast_source_to_sync = broadcaster; } if (err != 0) { diff --git a/tests/bluetooth/tester/src/audio/btp_bap_unicast.c b/tests/bluetooth/tester/src/audio/btp_bap_unicast.c index e839a0ddb767..c06795e8267a 100644 --- a/tests/bluetooth/tester/src/audio/btp_bap_unicast.c +++ b/tests/bluetooth/tester/src/audio/btp_bap_unicast.c @@ -511,7 +511,6 @@ static void stream_configured_cb(struct bt_bap_stream *stream, u_stream->conn_id = bt_conn_index(stream->conn); u_conn = &connections[u_stream->conn_id]; - u_stream->ase_id = info.id; stream_state_changed(stream); } @@ -1272,6 +1271,12 @@ static int client_configure_codec(struct btp_bap_unicast_connection *u_conn, str memcpy(&stream->codec_cfg, codec_cfg, sizeof(*codec_cfg)); err = bt_bap_stream_config(conn, stream_unicast_to_bap(stream), ep, &stream->codec_cfg); + + if (err == 0) { + stream->ase_id = ase_id; + } else { + stream->in_use = false; + } } else { /* Reconfigure a stream */ memcpy(&stream->codec_cfg, codec_cfg, sizeof(*codec_cfg)); diff --git a/tests/bluetooth/tester/src/audio/btp_csis.c b/tests/bluetooth/tester/src/audio/btp_csis.c index cd62adf6f5eb..4e3662487684 100644 --- a/tests/bluetooth/tester/src/audio/btp_csis.c +++ b/tests/bluetooth/tester/src/audio/btp_csis.c @@ -24,7 +24,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); #define BTP_STATUS_VAL(err) (err) ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS static struct bt_csip_set_member_svc_inst *csis_svc_inst; -static bool enc_sirk; +static uint8_t sirk_read_response; static uint8_t csis_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -65,15 +65,61 @@ static uint8_t csis_get_member_rsi(const void *cmd, uint16_t cmd_len, return BTP_STATUS_VAL(err); } -static uint8_t csis_sirk_type(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +static uint8_t csis_set_sirk_type(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { - const struct btp_csis_sirk_type_cmd *cp = cmd; + const struct btp_csis_sirk_set_type_cmd *cp = cmd; + + switch (cp->type) { + case BTP_CSIS_SIRK_TYPE_PLAINTEXT: + LOG_DBG("SIRK type: plain text"); + sirk_read_response = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT; + break; + case BTP_CSIS_SIRK_TYPE_ENCRYPTED: + LOG_DBG("SIRK type: encrypted"); + sirk_read_response = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC; + break; + case BTP_CSIS_SIRK_TYPE_OOB_ONLY: + LOG_DBG("SIRK type: OOB procedure only"); + sirk_read_response = BT_CSIP_READ_SIRK_REQ_RSP_OOB_ONLY; + break; + default: + LOG_ERR("Unknown SIRK type: %u", cp->type); + return BTP_STATUS_FAILED; + } - enc_sirk = cp->encrypted != 0U; + return BTP_STATUS_SUCCESS; +} - LOG_DBG("SIRK type: %s", enc_sirk ? "encrypted" : "plain text"); +static uint8_t csis_set_sirk(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_csis_set_sirk_cmd *cp = cmd; + int err = -ENOENT; - return BTP_STATUS_SUCCESS; + LOG_DBG("Setting new SIRK"); + + if (csis_svc_inst != NULL) { + err = bt_csip_set_member_sirk(csis_svc_inst, cp->sirk); + } else { + LOG_DBG("No CSIS instance registered"); + } + + return BTP_STATUS_VAL(err); +} + +static uint8_t csis_set_set_size(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_csis_set_set_size_cmd *cp = cmd; + int err = -ENOENT; + + LOG_DBG("Setting new set size %u and rank %u", cp->set_size, cp->rank); + + if (csis_svc_inst != NULL) { + err = bt_csip_set_member_set_size_and_rank(csis_svc_inst, cp->set_size, cp->rank); + } else { + LOG_DBG("No CSIS instance registered"); + } + + return BTP_STATUS_VAL(err); } static const struct btp_handler csis_handlers[] = { @@ -94,9 +140,19 @@ static const struct btp_handler csis_handlers[] = { .func = csis_get_member_rsi, }, { - .opcode = BTP_CSIS_ENC_SIRK_TYPE, - .expect_len = sizeof(struct btp_csis_sirk_type_cmd), - .func = csis_sirk_type, + .opcode = BTP_CSIS_SET_SIRK_TYPE, + .expect_len = sizeof(struct btp_csis_sirk_set_type_cmd), + .func = csis_set_sirk_type, + }, + { + .opcode = BTP_CSIS_SET_SIRK, + .expect_len = sizeof(struct btp_csis_set_sirk_cmd), + .func = csis_set_sirk, + }, + { + .opcode = BTP_CSIS_SET_SET_SIZE, + .expect_len = sizeof(struct btp_csis_set_set_size_cmd), + .func = csis_set_set_size, }, }; @@ -108,11 +164,7 @@ static void lock_changed_cb(struct bt_conn *conn, struct bt_csip_set_member_svc_ static uint8_t sirk_read_cb(struct bt_conn *conn, struct bt_csip_set_member_svc_inst *svc_inst) { - if (enc_sirk) { - return BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC; - } else { - return BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT; - } + return sirk_read_response; } static struct bt_csip_set_member_cb csis_cb = { @@ -132,6 +184,8 @@ uint8_t tester_init_csis(void) }; int err = bt_csip_set_member_register(®ister_params, &csis_svc_inst); + sirk_read_response = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT; + tester_register_command_handlers(BTP_SERVICE_ID_CSIS, csis_handlers, ARRAY_SIZE(csis_handlers)); diff --git a/tests/bluetooth/tester/src/audio/btp_vcp.c b/tests/bluetooth/tester/src/audio/btp_vcp.c index 9205181a0db9..ec78de2c0435 100644 --- a/tests/bluetooth/tester/src/audio/btp_vcp.c +++ b/tests/bluetooth/tester/src/audio/btp_vcp.c @@ -140,6 +140,43 @@ static uint8_t unmute(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +static void set_register_params(uint8_t gain_mode, uint8_t step, + bool muted, uint8_t volume); + +static uint8_t register_vcs(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + static bool vcs_registered_flag; + const struct btp_vcs_register_cmd *cp = cmd; + int err; + + LOG_DBG("Registering VCS"); + + if (vcs_registered_flag) { + return BTP_STATUS_FAILED; + } + + bool muted = (cp->flags & BTP_VCS_REGISTER_FLAG_MUTED) != 0; + + set_register_params(BT_AICS_MODE_MANUAL, cp->step, muted, cp->volume); + + err = bt_vcp_vol_rend_register(&vcp_register_param); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + err = bt_vcp_vol_rend_included_get(&included); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + aics_server_instance.aics_cnt = included.aics_cnt; + aics_server_instance.aics = included.aics; + vcs_registered_flag = true; + + return BTP_STATUS_SUCCESS; +} + static void vcs_state_cb(struct bt_conn *conn, int err, uint8_t volume, uint8_t mute) { LOG_DBG("VCP state cb err (%d)", err); @@ -187,6 +224,11 @@ static const struct btp_handler vcs_handlers[] = { .expect_len = 0, .func = unmute, }, + { + .opcode = BTP_VCS_REGISTER, + .expect_len = sizeof(struct btp_vcs_register_cmd), + .func = register_vcs, + }, }; /* Volume Offset Control Service */ @@ -463,7 +505,8 @@ struct bt_aics_cb aics_server_cb = { }; /* General profile handling */ -static void set_register_params(uint8_t gain_mode) +static void set_register_params(uint8_t gain_mode, uint8_t step, + bool muted, uint8_t volume) { char input_desc[CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT] [BT_AICS_MAX_INPUT_DESCRIPTION_SIZE]; @@ -495,31 +538,18 @@ static void set_register_params(uint8_t gain_mode) vcp_register_param.aics_param[i].cb = &aics_server_cb; } - vcp_register_param.step = 1; - vcp_register_param.mute = BT_VCP_STATE_UNMUTED; - vcp_register_param.volume = 100; + vcp_register_param.step = step; + if (muted) { + vcp_register_param.mute = BT_VCP_STATE_MUTED; + } else { + vcp_register_param.mute = BT_VCP_STATE_UNMUTED; + } + vcp_register_param.volume = volume; vcp_register_param.cb = &vcs_cb; } uint8_t tester_init_vcs(void) { - int err; - - set_register_params(BT_AICS_MODE_MANUAL); - - err = bt_vcp_vol_rend_register(&vcp_register_param); - if (err) { - return BTP_STATUS_FAILED; - } - - err = bt_vcp_vol_rend_included_get(&included); - if (err) { - return BTP_STATUS_FAILED; - } - - aics_server_instance.aics_cnt = included.aics_cnt; - aics_server_instance.aics = included.aics; - tester_register_command_handlers(BTP_SERVICE_ID_VCS, vcs_handlers, ARRAY_SIZE(vcs_handlers)); diff --git a/tests/bluetooth/tester/src/btp/btp_gap.h b/tests/bluetooth/tester/src/btp/btp_gap.h index 924859c461c2..81c7ba723b6c 100644 --- a/tests/bluetooth/tester/src/btp/btp_gap.h +++ b/tests/bluetooth/tester/src/btp/btp_gap.h @@ -578,13 +578,13 @@ struct btp_gap_periodic_biginfo_ev { uint8_t encryption; } __packed; -#if defined(CONFIG_BT_EXT_ADV) struct bt_le_per_adv_param; struct bt_le_per_adv_sync_param; struct bt_le_adv_param; struct bt_data; struct bt_le_ext_adv *tester_gap_ext_adv_get(uint8_t ext_adv_idx); struct bt_le_per_adv_sync *tester_gap_padv_get(void); +int tester_gap_clear_adv_instance(struct bt_le_ext_adv *ext_adv); int tester_gap_create_adv_instance(struct bt_le_adv_param *param, uint8_t own_addr_type, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len, @@ -598,4 +598,3 @@ int tester_gap_padv_start(struct bt_le_ext_adv *ext_adv); int tester_gap_padv_stop(struct bt_le_ext_adv *ext_adv); int tester_gap_padv_create_sync(struct bt_le_per_adv_sync_param *create_params); int tester_gap_padv_stop_sync(void); -#endif /* defined(CONFIG_BT_EXT_ADV) */ diff --git a/tests/bluetooth/tester/src/btp/btp_mesh.h b/tests/bluetooth/tester/src/btp/btp_mesh.h index 353971261b43..78074e1001e0 100644 --- a/tests/bluetooth/tester/src/btp/btp_mesh.h +++ b/tests/bluetooth/tester/src/btp/btp_mesh.h @@ -1194,7 +1194,7 @@ struct btp_mesh_prov_node_added_ev { struct btp_mesh_model_recv_ev { uint16_t src; uint16_t dst; - uint8_t payload_len; + uint16_t payload_len; uint8_t payload[]; } __packed; diff --git a/tests/bluetooth/tester/src/btp_gap.c b/tests/bluetooth/tester/src/btp_gap.c index 1344933eec52..80b30467bd9d 100644 --- a/tests/bluetooth/tester/src/btp_gap.c +++ b/tests/bluetooth/tester/src/btp_gap.c @@ -600,6 +600,21 @@ static int tester_gap_ext_adv_idx_free_get(void) return -ENOMEM; } +static int tester_gap_ext_adv_idx_get(struct bt_le_ext_adv *ext_adv) +{ + if (!IS_ENABLED(CONFIG_BT_EXT_ADV)) { + return -ENOTSUP; + } + + for (int i = 0; i < ARRAY_SIZE(ext_adv_sets); i++) { + if (ext_adv_sets[i] == ext_adv) { + return i; + } + } + + return -EINVAL; +} + int tester_gap_start_ext_adv(struct bt_le_ext_adv *ext_adv) { if (!IS_ENABLED(CONFIG_BT_EXT_ADV)) { @@ -644,6 +659,8 @@ int tester_gap_stop_ext_adv(struct bt_le_ext_adv *ext_adv) return -EINVAL; } + tester_gap_clear_adv_instance(ext_adv); + atomic_clear_bit(¤t_settings, BTP_GAP_SETTINGS_ADVERTISING); return 0; @@ -750,6 +767,29 @@ static uint8_t set_bondable(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +int tester_gap_clear_adv_instance(struct bt_le_ext_adv *ext_adv) +{ + if (!IS_ENABLED(CONFIG_BT_EXT_ADV)) { + return -ENOTSUP; + } + + if (ext_adv == NULL) { + LOG_ERR("Invalid ext_adv"); + return -EINVAL; + } + + int index = tester_gap_ext_adv_idx_get(ext_adv); + + if (index < 0) { + LOG_ERR("Failed to get ext_adv index"); + return -EINVAL; + } + + ext_adv_sets[index] = NULL; + + return 0; +} + int tester_gap_create_adv_instance(struct bt_le_adv_param *param, uint8_t own_addr_type, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len, uint32_t *settings, @@ -973,7 +1013,7 @@ static uint8_t stop_advertising(const void *cmd, uint16_t cmd_len, if (IS_ENABLED(CONFIG_BT_EXT_ADV) && atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_EXTENDED_ADVERTISING)) { - err = bt_le_ext_adv_stop(gap_ext_adv); + err = tester_gap_stop_ext_adv(gap_ext_adv); } else { err = bt_le_adv_stop(); } diff --git a/tests/bluetooth/tester/src/btp_mesh.c b/tests/bluetooth/tester/src/btp_mesh.c index 11156f36c7ec..26ab447c8269 100644 --- a/tests/bluetooth/tester/src/btp_mesh.c +++ b/tests/bluetooth/tester/src/btp_mesh.c @@ -1175,9 +1175,17 @@ static void link_close(bt_mesh_prov_bearer_t bearer) tester_event(BTP_SERVICE_ID_MESH, BTP_MESH_EV_PROV_LINK_CLOSED, &ev, sizeof(ev)); } -static int output_number(bt_mesh_output_action_t action, uint32_t number) +static int output_numeric(bt_mesh_output_action_t action, uint8_t *numeric, size_t size) { struct btp_mesh_out_number_action_ev ev; + uint32_t number; + + if (size > sizeof(number)) { + LOG_ERR("Unsupported size %zu", size); + return -EINVAL; + } + + number = sys_get_le32(numeric); LOG_DBG("action 0x%04x number 0x%08x", action, number); @@ -1297,7 +1305,7 @@ static struct bt_mesh_prov prov = { .uuid = dev_uuid, .static_val = static_auth, .static_val_len = sizeof(static_auth), - .output_number = output_number, + .output_numeric = output_numeric, .output_string = output_string, .input = input, .link_open = link_open, @@ -1505,7 +1513,7 @@ static uint8_t input_number(const void *cmd, uint16_t cmd_len, LOG_DBG("number 0x%04x", number); - err = bt_mesh_input_number(number); + err = bt_mesh_input_numeric((uint8_t *)&cp->number, sizeof(cp->number)); if (err) { return BTP_STATUS_FAILED; } @@ -5332,12 +5340,12 @@ void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const voi void model_recv_ev(uint16_t src, uint16_t dst, const void *payload, size_t payload_len) { - NET_BUF_SIMPLE_DEFINE(buf, UINT8_MAX); + NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_RX_SDU_MAX + sizeof(struct btp_mesh_model_recv_ev)); struct btp_mesh_model_recv_ev *ev; LOG_DBG("src 0x%04x dst 0x%04x payload_len %zu", src, dst, payload_len); - if (payload_len > net_buf_simple_tailroom(&buf)) { + if (payload_len + sizeof(*ev) > net_buf_simple_tailroom(&buf)) { LOG_ERR("Payload size exceeds buffer size"); return; } diff --git a/tests/bluetooth/tester/sysbuild.cmake b/tests/bluetooth/tester/sysbuild.cmake index a9ddf1279471..b640a7d04936 100644 --- a/tests/bluetooth/tester/sysbuild.cmake +++ b/tests/bluetooth/tester/sysbuild.cmake @@ -2,8 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) - # For builds in the nrf5340, we build the netcore image with the controller - set(NET_APP hci_ipc) set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) @@ -13,6 +11,13 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) BOARD ${SB_CONFIG_NET_CORE_BOARD} ) + if(SB_CONFIG_SOC_NRF5340_CPUAPP) + set(${NET_APP}_SNIPPET + "bt-ll-sw-split" + CACHE INTERNAL "" + ) + endif() + set(${NET_APP}_EXTRA_CONF_FILE ${APP_DIR}/overlay-bt_ll_sw_split.conf CACHE INTERNAL "" diff --git a/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 000000000000..24e3d84ecf96 --- /dev/null +++ b/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1,39 @@ +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_ISR_STACK_SIZE=1024 +CONFIG_IDLE_STACK_SIZE=256 +CONFIG_MAIN_STACK_SIZE=1024 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_IPC_SERVICE_BACKEND_RPMSG_WQ_STACK_SIZE=512 +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y + +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +# Host +CONFIG_BT_BROADCASTER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PER_ADV=y +CONFIG_BT_PER_ADV_SYNC=y + +# Controller +CONFIG_BT_LL_SW_SPLIT=n +CONFIG_BT_LL_SOFTDEVICE=y +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 + +# Enable PSA RNG +CONFIG_PSA_CRYPTO_DRIVER_OBERON=n +CONFIG_PSA_SSF_CRYPTO_CLIENT=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_NRF_SECURITY=y diff --git a/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 000000000000..e34567fe834a --- /dev/null +++ b/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,13 @@ +// Enable PSA RNG +/ { + chosen { + zephyr,entropy = &psa_rng; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; + + /delete-node/ prng; +}; diff --git a/tests/bluetooth/tester/sysbuild/hci_ipc/prj.conf b/tests/bluetooth/tester/sysbuild/hci_ipc/prj.conf new file mode 100644 index 000000000000..08b1aed9e7f6 --- /dev/null +++ b/tests/bluetooth/tester/sysbuild/hci_ipc/prj.conf @@ -0,0 +1,23 @@ +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_HEAP_MEM_POOL_SIZE=4096 + +CONFIG_MAIN_STACK_SIZE=512 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=16 + + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + +# Enable and adjust the below value as necessary +# CONFIG_BT_BUF_EVT_RX_COUNT=16 +# CONFIG_BT_BUF_EVT_RX_SIZE=255 +# CONFIG_BT_BUF_ACL_RX_SIZE=255 +# CONFIG_BT_BUF_ACL_TX_SIZE=251 +# CONFIG_BT_BUF_CMD_TX_SIZE=255 diff --git a/tests/boards/nrf/comp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay b/tests/boards/nrf/comp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay index aaf1006300a5..c928e7eff243 100644 --- a/tests/boards/nrf/comp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay +++ b/tests/boards/nrf/comp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay @@ -5,6 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { aliases { test-comp = ∁ @@ -30,9 +32,9 @@ &comp { status = "okay"; - psel = "AIN4"; + psel = ; refsel = "AREF"; - extrefsel = "AIN3"; + extrefsel = ; sp-mode = "NORMAL"; th-up = <36>; th-down = <30>; diff --git a/tests/boards/nrf/comp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay b/tests/boards/nrf/comp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay index aaf1006300a5..c928e7eff243 100644 --- a/tests/boards/nrf/comp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay +++ b/tests/boards/nrf/comp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay @@ -5,6 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { aliases { test-comp = ∁ @@ -30,9 +32,9 @@ &comp { status = "okay"; - psel = "AIN4"; + psel = ; refsel = "AREF"; - extrefsel = "AIN3"; + extrefsel = ; sp-mode = "NORMAL"; th-up = <36>; th-down = <30>; diff --git a/tests/boards/nrf/comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/boards/nrf/comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 4e9e898ea184..27008ba6760f 100644 --- a/tests/boards/nrf/comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/boards/nrf/comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { aliases { test-comp = ∁ @@ -25,9 +27,9 @@ &comp { status = "okay"; - psel = "AIN5"; + psel = ; refsel = "AREF"; - extrefsel = "AIN1"; + extrefsel = ; sp-mode = "HIGH"; th-up = <36>; th-down = <30>; diff --git a/tests/boards/nrf/comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/boards/nrf/comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index d6492e37c343..5695f7d90dcd 100644 --- a/tests/boards/nrf/comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/boards/nrf/comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { aliases { test-comp = ∁ @@ -29,9 +31,9 @@ &comp { status = "okay"; - psel = "AIN4"; + psel = ; refsel = "AREF"; - extrefsel = "AIN3"; + extrefsel = ; sp-mode = "NORMAL"; th-up = <36>; th-down = <30>; diff --git a/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 45cefc0815bb..94087309aee9 100644 --- a/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay +++ b/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -5,6 +5,8 @@ * AIN4 (P1.06) tied to VDD */ +#include + / { aliases { test-comp = ∁ @@ -22,9 +24,9 @@ &comp { status = "okay"; - psel = "AIN4"; + psel = ; refsel = "AREF"; - extrefsel = "AIN3"; + extrefsel = ; sp-mode = "NORMAL"; th-up = <36>; th-down = <30>; diff --git a/tests/boards/nrf/comp/src/test.c b/tests/boards/nrf/comp/src/test.c index 1d1876e76faa..481760da5bd4 100644 --- a/tests/boards/nrf/comp/src/test.c +++ b/tests/boards/nrf/comp/src/test.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -13,14 +14,11 @@ static const struct device *test_dev = DEVICE_DT_GET(DT_ALIAS(test_comp)); static const struct gpio_dt_spec test_pin_1 = GPIO_DT_SPEC_GET(DT_PATH(zephyr_user), first_gpios); static const struct gpio_dt_spec test_pin_2 = GPIO_DT_SPEC_GET(DT_PATH(zephyr_user), second_gpios); -#define TEST_COMP_SE_PSEL_AIN _CONCAT(COMP_NRF_COMP_PSEL_AIN, \ - CONFIG_TEST_COMP_SE_PSEL_AIN_INDEX) -#define TEST_COMP_SE_EXTREFSEL_AIN _CONCAT(COMP_NRF_COMP_EXTREFSEL_AIN, \ - CONFIG_TEST_COMP_SE_EXTREFSEL_AIN_INDEX) -#define TEST_COMP_DIFF_PSEL_AIN _CONCAT(COMP_NRF_COMP_PSEL_AIN, \ - CONFIG_TEST_COMP_DIFF_PSEL_AIN_INDEX) -#define TEST_COMP_DIFF_EXTREFSEL_AIN _CONCAT(COMP_NRF_COMP_EXTREFSEL_AIN, \ - CONFIG_TEST_COMP_DIFF_EXTREFSEL_AIN_INDEX) +#define TEST_COMP_SE_PSEL_AIN _CONCAT(NRF_COMP_AIN, CONFIG_TEST_COMP_SE_PSEL_AIN_INDEX) +#define TEST_COMP_SE_EXTREFSEL_AIN _CONCAT(NRF_COMP_AIN, CONFIG_TEST_COMP_SE_EXTREFSEL_AIN_INDEX) +#define TEST_COMP_DIFF_PSEL_AIN _CONCAT(NRF_COMP_AIN, CONFIG_TEST_COMP_DIFF_PSEL_AIN_INDEX) +#define TEST_COMP_DIFF_EXTREFSEL_AIN \ + _CONCAT(NRF_COMP_AIN, CONFIG_TEST_COMP_DIFF_EXTREFSEL_AIN_INDEX) struct comp_nrf_comp_se_config comp_se_config = { .psel = TEST_COMP_SE_PSEL_AIN, diff --git a/tests/boards/nrf/coresight_stm/prj.conf b/tests/boards/nrf/coresight_stm/prj.conf index 1e935e973c76..9ee7cf8cc03a 100644 --- a/tests/boards/nrf/coresight_stm/prj.conf +++ b/tests/boards/nrf/coresight_stm/prj.conf @@ -1 +1,2 @@ CONFIG_LOG=y +CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y diff --git a/tests/boards/nrf/dmm/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/boards/nrf/dmm/boards/nrf5340dk_nrf5340_cpuapp.overlay index 3e0b1b4d5356..48a4e8adc264 100644 --- a/tests/boards/nrf/dmm/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/tests/boards/nrf/dmm/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + / { aliases { dut-cache = &spi1; @@ -52,3 +58,7 @@ pinctrl-1 = <&spi3_sleep_alt>; pinctrl-names = "default", "sleep"; }; + +cycle_timer: &timer1 { + status = "okay"; +}; diff --git a/tests/boards/nrf/dmm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/boards/nrf/dmm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index e3924657b86e..2507dd83dfe3 100644 --- a/tests/boards/nrf/dmm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/boards/nrf/dmm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + / { aliases { dut-cache = &spi120; @@ -58,3 +64,7 @@ pinctrl-names = "default", "sleep"; memory-regions = <&dma_fast_region>; }; + +cycle_timer: &timer120 { + status = "okay"; +}; diff --git a/tests/boards/nrf/dmm/prj.conf b/tests/boards/nrf/dmm/prj.conf index 9467c2926896..c05afbb6ad35 100644 --- a/tests/boards/nrf/dmm/prj.conf +++ b/tests/boards/nrf/dmm/prj.conf @@ -1 +1,6 @@ CONFIG_ZTEST=y +CONFIG_ZTRESS=y +CONFIG_ASSERT=n +CONFIG_SPIN_VALIDATE=n +CONFIG_TEST_EXTRA_STACK_SIZE=512 +CONFIG_COUNTER=y diff --git a/tests/boards/nrf/dmm/src/main.c b/tests/boards/nrf/dmm/src/main.c index 214a90697525..58b7e891c795 100644 --- a/tests/boards/nrf/dmm/src/main.c +++ b/tests/boards/nrf/dmm/src/main.c @@ -9,9 +9,14 @@ #include #include #include +#include +#include +#include #include +#define IS_ALIGNED64(x) IS_ALIGNED(x, sizeof(uint64_t)) + #define DUT_CACHE DT_ALIAS(dut_cache) #define DUT_NOCACHE DT_ALIAS(dut_nocache) @@ -25,7 +30,7 @@ #if CONFIG_DCACHE BUILD_ASSERT(DMM_ALIGN_SIZE(DUT_CACHE) == CONFIG_DCACHE_LINE_SIZE); -BUILD_ASSERT(DMM_ALIGN_SIZE(DUT_NOCACHE) == 1); +BUILD_ASSERT(DMM_ALIGN_SIZE(DUT_NOCACHE) == sizeof(uint32_t)); #endif struct dmm_test_region { @@ -57,13 +62,49 @@ static const struct dmm_test_region dmm_test_regions[DMM_TEST_REGION_COUNT] = { .size = DMM_TEST_GET_REG_SIZE(DUT_NOCACHE) }, }; +static const struct device *counter = DEVICE_DT_GET(DT_NODELABEL(cycle_timer)); +static uint32_t t_delta; + +static uint32_t ts_get(void) +{ + uint32_t t; + + (void)counter_get_value(counter, &t); + return t; +} + +static uint32_t ts_from_get(uint32_t from) +{ + return ts_get() - from; +} + +static uint32_t cyc_to_us(uint32_t cyc) +{ + return counter_ticks_to_us(counter, cyc); +} + +static uint32_t cyc_to_rem_ns(uint32_t cyc) +{ + uint32_t us = counter_ticks_to_us(counter, cyc); + uint32_t ns; + + cyc = cyc - counter_us_to_ticks(counter, (uint64_t)us); + ns = counter_ticks_to_us(counter, 1000 * cyc); + + return ns; +} static void *test_setup(void) { static struct dmm_fixture fixture; + uint32_t t; + counter_start(counter); + t = ts_get(); + t_delta = ts_get() - t; memcpy(fixture.regions, dmm_test_regions, sizeof(dmm_test_regions)); fixture.fill_value = 0x1; + return &fixture; } @@ -79,13 +120,25 @@ static bool dmm_buffer_in_region_check(struct dmm_test_region *dtr, void *buf, s } static void dmm_check_output_buffer(struct dmm_test_region *dtr, uint32_t *fill_value, - void *data, size_t size, bool was_prealloc, bool is_cached) + void *data, size_t size, bool was_prealloc, + bool is_cached, bool print_report) { void *buf; int retval; + uint32_t t; + bool aligned; memset(data, (*fill_value)++, size); + t = ts_get(); retval = dmm_buffer_out_prepare(dtr->mem_reg, data, size, &buf); + t = ts_from_get(t); + aligned = IS_ALIGNED64(data) && IS_ALIGNED64(buf) && IS_ALIGNED64(size); + + if (print_report) { + TC_PRINT("%saligned buffer out prepare size:%d buf:%p took %d.%dus (%d cycles)\n", + aligned ? "" : "not ", size, buf, cyc_to_us(t), cyc_to_rem_ns(t), t); + } + zassert_ok(retval); if (IS_ENABLED(CONFIG_DCACHE) && is_cached) { zassert_true(IS_ALIGNED(buf, CONFIG_DCACHE_LINE_SIZE)); @@ -104,21 +157,37 @@ static void dmm_check_output_buffer(struct dmm_test_region *dtr, uint32_t *fill_ sys_cache_data_invd_range(buf, size); zassert_mem_equal(buf, data, size); + t = ts_get(); retval = dmm_buffer_out_release(dtr->mem_reg, buf); + t = ts_from_get(t); + if (print_report) { + TC_PRINT("buffer out release buf:%p size:%d took %d.%dus (%d cycles)\n", + buf, size, cyc_to_us(t), cyc_to_rem_ns(t), t); + } zassert_ok(retval); } static void dmm_check_input_buffer(struct dmm_test_region *dtr, uint32_t *fill_value, - void *data, size_t size, bool was_prealloc, bool is_cached) + void *data, size_t size, bool was_prealloc, + bool is_cached, bool print_report) { void *buf; int retval; + uint32_t t; uint8_t intermediate_buf[128]; + bool aligned; - zassert_true(size < sizeof(intermediate_buf)); + zassert_true(size <= sizeof(intermediate_buf)); + t = ts_get(); retval = dmm_buffer_in_prepare(dtr->mem_reg, data, size, &buf); + t = ts_from_get(t); + aligned = IS_ALIGNED64(data) && IS_ALIGNED64(buf) && IS_ALIGNED64(size); zassert_ok(retval); + if (print_report) { + TC_PRINT("%saligned buffer in prepare buf:%p size:%d took %d.%dus (%d cycles)\n", + aligned ? "" : "not ", buf, size, cyc_to_us(t), cyc_to_rem_ns(t), t); + } if (IS_ENABLED(CONFIG_DCACHE) && is_cached) { zassert_true(IS_ALIGNED(buf, CONFIG_DCACHE_LINE_SIZE)); } @@ -144,7 +213,13 @@ static void dmm_check_input_buffer(struct dmm_test_region *dtr, uint32_t *fill_v memset(buf, (*fill_value)++, size); } + t = ts_get(); retval = dmm_buffer_in_release(dtr->mem_reg, data, size, buf); + t = ts_from_get(t); + if (print_report) { + TC_PRINT("buffer in release buf:%p size:%d took %d.%dus (%d cycles)\n", + buf, size, cyc_to_us(t), cyc_to_rem_ns(t), t); + } zassert_ok(retval); zassert_mem_equal(data, intermediate_buf, size); @@ -152,10 +227,14 @@ static void dmm_check_input_buffer(struct dmm_test_region *dtr, uint32_t *fill_v ZTEST_USER_F(dmm, test_check_dev_cache_in_allocate) { - uint8_t user_data[16]; + uint8_t user_data[128] __aligned(sizeof(uint64_t)); dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, - user_data, sizeof(user_data), false, true); + user_data, 16, false, true, false); + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + user_data, 16, false, true, true); + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + user_data, sizeof(user_data), false, true, true); } ZTEST_USER_F(dmm, test_check_dev_cache_in_preallocate) @@ -163,15 +242,30 @@ ZTEST_USER_F(dmm, test_check_dev_cache_in_preallocate) static uint8_t user_data[16] DMM_MEMORY_SECTION(DUT_CACHE); dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, - user_data, sizeof(user_data), true, true); + user_data, sizeof(user_data), true, true, true); } ZTEST_USER_F(dmm, test_check_dev_cache_out_allocate) { - uint8_t user_data[16]; + uint8_t user_data[129] __aligned(sizeof(uint64_t)); + + /* First run to get code into ICACHE so that following runs has consistent timing. */ + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + user_data, 16, false, true, false); + + /* Aligned user buffer. */ + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + user_data, 16, false, true, true); + /* Unaligned user buffer. */ + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + &user_data[1], 16, false, true, true); + /* Aligned user buffer. */ dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, - user_data, sizeof(user_data), false, true); + user_data, sizeof(user_data) - 1, false, true, true); + /* Unaligned user buffer. */ + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + &user_data[1], sizeof(user_data) - 1, false, true, true); } ZTEST_USER_F(dmm, test_check_dev_cache_out_preallocate) @@ -179,15 +273,31 @@ ZTEST_USER_F(dmm, test_check_dev_cache_out_preallocate) static uint8_t user_data[16] DMM_MEMORY_SECTION(DUT_CACHE); dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, - user_data, sizeof(user_data), true, true); + user_data, sizeof(user_data), true, true, true); } ZTEST_USER_F(dmm, test_check_dev_nocache_in_allocate) { - uint8_t user_data[16]; + uint8_t user_data[129] __aligned(sizeof(uint64_t)); + + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + user_data, 16, false, false, false); + + /* Aligned user buffer. */ + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + user_data, 16, false, false, true); + + /* Unaligned user buffer. */ + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + &user_data[1], 16, false, false, true); + /* Aligned user buffer. */ dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, - user_data, sizeof(user_data), false, false); + user_data, sizeof(user_data) - 1, false, false, true); + + /* Unaligned user buffer. */ + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + &user_data[1], sizeof(user_data) - 1, false, false, true); } ZTEST_USER_F(dmm, test_check_dev_nocache_in_preallocate) @@ -195,15 +305,30 @@ ZTEST_USER_F(dmm, test_check_dev_nocache_in_preallocate) static uint8_t user_data[16] DMM_MEMORY_SECTION(DUT_NOCACHE); dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, - user_data, sizeof(user_data), true, false); + user_data, sizeof(user_data), true, false, true); } ZTEST_USER_F(dmm, test_check_dev_nocache_out_allocate) { - uint8_t user_data[16]; + uint8_t user_data[129] __aligned(sizeof(uint64_t)); + + /* First run to get code into ICACHE so that following results are consistent. */ + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + user_data, 16, false, false, false); + /* Aligned user buffer. */ + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + user_data, 16, false, false, true); + /* Unaligned user buffer. */ + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + &user_data[1], 16, false, false, true); + + /* Aligned user buffer. */ + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + user_data, sizeof(user_data) - 1, false, false, true); + /* Unaligned user buffer. */ dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, - user_data, sizeof(user_data), false, false); + &user_data[1], sizeof(user_data) - 1, false, false, true); } ZTEST_USER_F(dmm, test_check_dev_nocache_out_preallocate) @@ -211,7 +336,233 @@ ZTEST_USER_F(dmm, test_check_dev_nocache_out_preallocate) static uint8_t user_data[16] DMM_MEMORY_SECTION(DUT_NOCACHE); dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, - user_data, sizeof(user_data), true, false); + user_data, sizeof(user_data), true, false, true); +} + +ZTEST_USER_F(dmm, test_check_multiple_alloc_and_free) +{ + int retval; + uint8_t buf[256]; + uint8_t buf2[32]; + void *dmm_buf; + void *dmm_buf2; + void *mem_reg = fixture->regions[DMM_TEST_REGION_NOCACHE].mem_reg; + uintptr_t start_address; + uint32_t curr_use, max_use; + + if (IS_ENABLED(CONFIG_DMM_STATS)) { + retval = dmm_stats_get(mem_reg, &start_address, &curr_use, &max_use); + zassert_ok(retval); + } + + memset(buf, 0, sizeof(buf)); + memset(buf2, 0, sizeof(buf2)); + + retval = dmm_buffer_out_prepare(mem_reg, (void *)buf, sizeof(buf), &dmm_buf); + zassert_ok(retval); + zassert_true(dmm_buf != NULL); + + retval = dmm_buffer_out_prepare(mem_reg, (void *)buf2, sizeof(buf2), &dmm_buf2); + zassert_ok(retval); + zassert_true(dmm_buf2 != NULL); + + retval = dmm_buffer_out_release(mem_reg, dmm_buf2); + zassert_ok(retval); + zassert_true(dmm_buf != NULL); + + retval = dmm_buffer_out_release(mem_reg, dmm_buf); + zassert_ok(retval); + zassert_true(dmm_buf != NULL); + + if (IS_ENABLED(CONFIG_DMM_STATS)) { + uint32_t curr_use2; + + retval = dmm_stats_get(mem_reg, &start_address, &curr_use2, &max_use); + zassert_ok(retval); + zassert_equal(curr_use, curr_use2); + TC_PRINT("Stats start_address:%p current use:%d%% max use:%d%%\n", + (void *)start_address, curr_use2, max_use); + } +} + +struct dmm_stress_data { + void *mem_reg; + void *alloc_ptr[32]; + uint8_t alloc_token[32]; + size_t alloc_len[32]; + atomic_t alloc_mask; + atomic_t busy_mask; + atomic_t fails; + atomic_t cnt; + bool cached; +}; + +static void stress_free_op(struct dmm_stress_data *data, int prio, int id) +{ + /* buffer is allocated. */ + uint8_t token = data->alloc_token[id]; + size_t len = data->alloc_len[id]; + uint8_t *ptr = data->alloc_ptr[id]; + int rv; + + for (int j = 0; j < len; j++) { + uint8_t exp_val = (uint8_t)(token + j); + + if (ptr[j] != exp_val) { + for (int k = 0; k < len; k++) { + printk("%02x ", ptr[k]); + } + } + zassert_equal(ptr[j], exp_val, "At %d got:%d exp:%d, len:%d id:%d, alloc_cnt:%d", + j, ptr[j], exp_val, len, id, (uint32_t)data->cnt); + } + + rv = dmm_buffer_in_release(data->mem_reg, ptr, len, ptr); + zassert_ok(rv); + /* Indicate that buffer is released. */ + atomic_and(&data->alloc_mask, ~BIT(id)); +} + +static bool stress_alloc_op(struct dmm_stress_data *data, int prio, int id) +{ + uint32_t r32 = sys_rand32_get(); + size_t len = r32 % 512; + uint8_t *ptr = data->alloc_ptr[id]; + int rv; + + /* Rarely allocate bigger buffer. */ + if ((r32 & 0x7) == 0) { + len += 512; + } + + rv = dmm_buffer_in_prepare(data->mem_reg, &r32/*dummy*/, len, (void **)&ptr); + if (rv < 0) { + atomic_inc(&data->fails); + return true; + } + + uint8_t token = r32 >> 24; + + data->alloc_ptr[id] = ptr; + data->alloc_len[id] = len; + data->alloc_token[id] = token; + for (int j = 0; j < len; j++) { + ptr[j] = (uint8_t)(j + token); + } + if (data->cached) { + sys_cache_data_flush_range(ptr, len); + } + atomic_inc(&data->cnt); + return false; +} + +bool stress_func(void *user_data, uint32_t cnt, bool last, int prio) +{ + struct dmm_stress_data *data = user_data; + uint32_t r = sys_rand32_get(); + int rpt = r & 0x3; + + r >>= 2; + + for (int i = 0; i < rpt + 1; i++) { + int id = r % 32; + int key; + bool free_op; + bool clear_bit; + + key = irq_lock(); + if ((data->busy_mask & BIT(id)) == 0) { + data->busy_mask |= BIT(id); + if (data->alloc_mask & BIT(id)) { + free_op = true; + } else { + data->alloc_mask |= BIT(id); + free_op = false; + } + } else { + irq_unlock(key); + continue; + } + + irq_unlock(key); + r >>= 5; + + if (free_op) { + stress_free_op(data, prio, id); + clear_bit = true; + } else { + clear_bit = stress_alloc_op(data, prio, id); + } + + key = irq_lock(); + data->busy_mask &= ~BIT(id); + if (clear_bit) { + data->alloc_mask &= ~BIT(id); + } + irq_unlock(key); + } + + return true; +} + +static void free_all(struct dmm_stress_data *data) +{ + while (data->alloc_mask) { + int id = 31 - __builtin_clz(data->alloc_mask); + + stress_free_op(data, 0, id); + data->alloc_mask &= ~BIT(id); + } +} + +static void stress_allocator(void *mem_reg, bool cached) +{ + uint32_t timeout = 3000; + struct dmm_stress_data ctx; + int rv; + uint32_t curr_use; + + if (mem_reg == NULL) { + ztest_test_skip(); + } + + memset(&ctx, 0, sizeof(ctx)); + ctx.mem_reg = mem_reg; + ctx.cached = cached; + + if (IS_ENABLED(CONFIG_DMM_STATS)) { + rv = dmm_stats_get(ctx.mem_reg, NULL, &curr_use, NULL); + zassert_ok(rv); + } + + ztress_set_timeout(K_MSEC(timeout)); + + ZTRESS_EXECUTE(ZTRESS_THREAD(stress_func, &ctx, INT32_MAX, INT32_MAX, Z_TIMEOUT_TICKS(4)), + ZTRESS_THREAD(stress_func, &ctx, INT32_MAX, INT32_MAX, Z_TIMEOUT_TICKS(4)), + ZTRESS_THREAD(stress_func, &ctx, INT32_MAX, INT32_MAX, Z_TIMEOUT_TICKS(4))); + + free_all(&ctx); + TC_PRINT("Executed %d allocation operation. Failed to allocate %d times.\n", + (uint32_t)ctx.cnt, (uint32_t)ctx.fails); + + if (IS_ENABLED(CONFIG_DMM_STATS)) { + uint32_t curr_use2; + + rv = dmm_stats_get(ctx.mem_reg, NULL, &curr_use2, NULL); + zassert_ok(rv); + zassert_equal(curr_use, curr_use2, "Unexpected usage got:%d exp:%d", + curr_use2, curr_use); + } +} + +ZTEST_F(dmm, test_stress_allocator_nocache) +{ + stress_allocator(fixture->regions[DMM_TEST_REGION_NOCACHE].mem_reg, false); +} + +ZTEST_F(dmm, test_stress_allocator_cache) +{ + stress_allocator(fixture->regions[DMM_TEST_REGION_CACHE].mem_reg, true); } ZTEST_SUITE(dmm, NULL, test_setup, NULL, test_cleanup, NULL); diff --git a/tests/boards/nrf/dmm/testcase.yaml b/tests/boards/nrf/dmm/testcase.yaml index b5f41f281a5b..7fc991d4824c 100644 --- a/tests/boards/nrf/dmm/testcase.yaml +++ b/tests/boards/nrf/dmm/testcase.yaml @@ -16,3 +16,14 @@ tests: - CONFIG_DCACHE=n platform_allow: - nrf54h20dk/nrf54h20/cpuapp + boards.nrf.dmm.stats: + extra_configs: + - CONFIG_DMM_STATS=y + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + boards.nrf.dmm.more_chunks: + extra_configs: + - CONFIG_DMM_STATS=y + - CONFIG_DMM_HEAP_CHUNKS=96 + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp diff --git a/tests/boards/nrf/hwinfo/reset_cause/src/main.c b/tests/boards/nrf/hwinfo/reset_cause/src/main.c index 7df98bce9bc1..4e4e3a1c5d44 100644 --- a/tests/boards/nrf/hwinfo/reset_cause/src/main.c +++ b/tests/boards/nrf/hwinfo/reset_cause/src/main.c @@ -134,6 +134,16 @@ static void print_supported_reset_cause(void) } else { LOG_INF("14: no support for RESET_TEMPERATURE"); } + if (supported & RESET_BOOTLOADER) { + LOG_INF("15: RESET_BOOTLOADER is supported"); + } else { + LOG_INF("15: no support for RESET_BOOTLOADER"); + } + if (supported & RESET_FLASH) { + LOG_INF("16: RESET_FLASH is supported"); + } else { + LOG_INF("16: no support for RESET_FLASH"); + } } else if (ret == -ENOSYS) { LOG_INF("hwinfo_get_supported_reset_cause() is NOT supported"); supported = 0; @@ -197,6 +207,12 @@ static void print_current_reset_cause(uint32_t *cause) if (*cause & RESET_TEMPERATURE) { LOG_INF("14: reset due to RESET_TEMPERATURE"); } + if (*cause & RESET_BOOTLOADER) { + LOG_INF("15: reset due to RESET_BOOTLOADER"); + } + if (*cause & RESET_FLASH) { + LOG_INF("16: reset due to RESET_FLASH"); + } } else if (ret == -ENOSYS) { LOG_INF("hwinfo_get_reset_cause() is NOT supported"); *cause = 0; diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf52840dk_nrf52840.overlay b/tests/boards/nrf/i2c/i2c_slave/boards/nrf52840dk_nrf52840.overlay index cb4debaa7e3c..8f9f7135f7b2 100644 --- a/tests/boards/nrf/i2c/i2c_slave/boards/nrf52840dk_nrf52840.overlay +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf52840dk_nrf52840.overlay @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Two loopbacks are required: + * P1.01 - P1.02 + * P1.03 - P1.04 + */ + / { aliases { i2c-slave = &i2c1; @@ -44,6 +55,7 @@ dut_twim: &i2c0 { pinctrl-1 = <&i2c0_sleep_alt>; pinctrl-names = "default", "sleep"; clock-frequency = ; + sensor: sensor@54 { reg = <0x54>; }; diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/boards/nrf/i2c/i2c_slave/boards/nrf5340dk_nrf5340_cpuapp.overlay index 2ccac66dc723..c1f2a3b559ee 100644 --- a/tests/boards/nrf/i2c/i2c_slave/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Two loopbacks are required: + * P0.04 - P0.05 + * P0.06 - P0.07 + */ + / { aliases { i2c-slave = &i2c2; @@ -44,6 +55,7 @@ dut_twim: &i2c1 { pinctrl-1 = <&i2c1_sleep_alt>; pinctrl-names = "default", "sleep"; clock-frequency = ; + sensor: sensor@54 { reg = <0x54>; }; diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 444db89627d2..4f6894cf8585 100644 --- a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Two loopbacks are required: + * P2.08 - P2.09 + * P1.02 - P1.03 + */ + / { aliases { i2c-slave = &i2c131; @@ -48,6 +59,7 @@ dut_twim: &i2c130 { pinctrl-names = "default", "sleep"; clock-frequency = ; memory-regions = <&cpuapp_dma_region>; + sensor: sensor@54 { reg = <0x54>; }; diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54h20dk_nrf54h20_cpuppr.overlay index fbfb1e55772d..b42391719983 100644 --- a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54h20dk_nrf54h20_cpuppr.overlay +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Two loopbacks are required: + * P2.08 - P2.09 + * P1.02 - P1.03 + */ + / { aliases { i2c-slave = &i2c131; @@ -47,6 +58,7 @@ dut_twim: &i2c130 { pinctrl-1 = <&i2c130_sleep_alt>; pinctrl-names = "default", "sleep"; clock-frequency = ; + sensor: sensor@54 { reg = <0x54>; }; diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index feaec96977c7..aed3aca12dcb 100644 --- a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -1,3 +1,14 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Two loopbacks are required: + * P1.08 - P1.09 + * P1.12 - P1.13 + */ + / { aliases { i2c-slave = &i2c22; @@ -47,6 +58,7 @@ dut_twim: &i2c21 { pinctrl-1 = <&i2c21_sleep_alt>; pinctrl-names = "default", "sleep"; clock-frequency = ; + sensor: sensor@54 { reg = <0x54>; }; diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp_ns.conf b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp_ns.conf new file mode 100644 index 000000000000..b01af3b36a7b --- /dev/null +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp_ns.conf @@ -0,0 +1 @@ +CONFIG_NRFX_TWIS22=y diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/i2c_speed_fast.overlay b/tests/boards/nrf/i2c/i2c_slave/i2c_speed_fast.overlay similarity index 100% rename from tests/boards/nrf/i2c/i2c_slave/boards/i2c_speed_fast.overlay rename to tests/boards/nrf/i2c/i2c_slave/i2c_speed_fast.overlay diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/i2c_speed_fast_plus.overlay b/tests/boards/nrf/i2c/i2c_slave/i2c_speed_fast_plus.overlay similarity index 100% rename from tests/boards/nrf/i2c/i2c_slave/boards/i2c_speed_fast_plus.overlay rename to tests/boards/nrf/i2c/i2c_slave/i2c_speed_fast_plus.overlay diff --git a/tests/boards/nrf/i2c/i2c_slave/testcase.yaml b/tests/boards/nrf/i2c/i2c_slave/testcase.yaml index 02a2ee5f7518..8e324bcaf563 100644 --- a/tests/boards/nrf/i2c/i2c_slave/testcase.yaml +++ b/tests/boards/nrf/i2c/i2c_slave/testcase.yaml @@ -15,6 +15,7 @@ tests: - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf52840dk/nrf52840 @@ -30,6 +31,7 @@ tests: - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf52840dk/nrf52840 @@ -39,7 +41,7 @@ tests: - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp extra_args: - - EXTRA_DTC_OVERLAY_FILE="boards/i2c_speed_fast.overlay" + - EXTRA_DTC_OVERLAY_FILE="i2c_speed_fast.overlay" boards.nrf.i2c.i2c_slave.fast_plus: platform_allow: - nrf5340dk/nrf5340/cpuapp @@ -50,4 +52,4 @@ tests: - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpuppr extra_args: - - EXTRA_DTC_OVERLAY_FILE="boards/i2c_speed_fast_plus.overlay" + - EXTRA_DTC_OVERLAY_FILE="i2c_speed_fast_plus.overlay" diff --git a/tests/boards/nrf/qdec/boards/bl54l15_dvk_nrf54l15_common.dtsi b/tests/boards/nrf/qdec/boards/bl54l15_dvk_nrf54l15_common.dtsi index 4db67a49a5e0..19ca5e83647f 100644 --- a/tests/boards/nrf/qdec/boards/bl54l15_dvk_nrf54l15_common.dtsi +++ b/tests/boards/nrf/qdec/boards/bl54l15_dvk_nrf54l15_common.dtsi @@ -5,12 +5,6 @@ */ / { - aliases { - qdec0 = &qdec20; - qenca = &phase_a; - qencb = &phase_b; - }; - encoder-emulate { compatible = "gpio-leds"; @@ -22,6 +16,14 @@ gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; }; }; + + qdec_loopbacks: loopbacks { + compatible = "test-qdec-loopbacks"; + loopback0 { + qdec = <&qdec20>; + qenc-emul-gpios = <&phase_a &phase_b>; + }; + }; }; &pinctrl { diff --git a/tests/boards/nrf/qdec/boards/bl54l15u_dvk_nrf54l15_common.dtsi b/tests/boards/nrf/qdec/boards/bl54l15u_dvk_nrf54l15_common.dtsi index 4db67a49a5e0..19ca5e83647f 100644 --- a/tests/boards/nrf/qdec/boards/bl54l15u_dvk_nrf54l15_common.dtsi +++ b/tests/boards/nrf/qdec/boards/bl54l15u_dvk_nrf54l15_common.dtsi @@ -5,12 +5,6 @@ */ / { - aliases { - qdec0 = &qdec20; - qenca = &phase_a; - qencb = &phase_b; - }; - encoder-emulate { compatible = "gpio-leds"; @@ -22,6 +16,14 @@ gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; }; }; + + qdec_loopbacks: loopbacks { + compatible = "test-qdec-loopbacks"; + loopback0 { + qdec = <&qdec20>; + qenc-emul-gpios = <&phase_a &phase_b>; + }; + }; }; &pinctrl { diff --git a/tests/boards/nrf/qdec/boards/nrf52840dk_nrf52840.overlay b/tests/boards/nrf/qdec/boards/nrf52840dk_nrf52840.overlay index 9ee3749b4ff8..0c098f238bd0 100644 --- a/tests/boards/nrf/qdec/boards/nrf52840dk_nrf52840.overlay +++ b/tests/boards/nrf/qdec/boards/nrf52840dk_nrf52840.overlay @@ -21,6 +21,14 @@ gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; }; }; + + qdec_loopbacks: loopbacks { + compatible = "test-qdec-loopbacks"; + loopback0 { + qdec = <&qdec0>; + qenc-emul-gpios = <&phase_a &phase_b>; + }; + }; }; &pinctrl { diff --git a/tests/boards/nrf/qdec/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/boards/nrf/qdec/boards/nrf5340dk_nrf5340_cpuapp.overlay index 22f5307a760a..04872e1de5c7 100644 --- a/tests/boards/nrf/qdec/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/tests/boards/nrf/qdec/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -4,12 +4,6 @@ */ / { - aliases { - qdec0 = &qdec1; - qenca = &phase_a; - qencb = &phase_b; - }; - encoder-emulate { compatible = "gpio-leds"; phase_a: phase_a { @@ -21,6 +15,14 @@ gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; }; }; + + qdec_loopbacks: loopbacks { + compatible = "test-qdec-loopbacks"; + loopback0 { + qdec = <&qdec1>; + qenc-emul-gpios = <&phase_a &phase_b>; + }; + }; }; &pinctrl { diff --git a/tests/boards/nrf/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/boards/nrf/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 78f3aa09ace4..7e43c70dac0f 100644 --- a/tests/boards/nrf/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/boards/nrf/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -11,21 +11,12 @@ */ / { - aliases { - qdec0 = &qdec130; - qdec1 = &qdec131; - qenca = &phase_a; - qencb = &phase_b; - qenca1 = &phase_a1; - qencb1 = &phase_b1; - }; - encoder-emulate { compatible = "gpio-leds"; - phase_a: phase_a { + phase_a0: phase_a0 { gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; }; - phase_b: phase_b { + phase_b0: phase_b0 { gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>; }; phase_a1: phase_a1 { @@ -35,6 +26,18 @@ gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>; }; }; + + qdec_loopbacks: loopbacks { + compatible = "test-qdec-loopbacks"; + loopback0 { + qdec = <&qdec130>; + qenc-emul-gpios = <&phase_a0 &phase_b0>; + }; + loopback1 { + qdec = <&qdec131>; + qenc-emul-gpios = <&phase_a1 &phase_b1>; + }; + }; }; &pinctrl { diff --git a/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_common.dtsi b/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_common.dtsi index 06a490d1da08..2b9db5d36352 100644 --- a/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_common.dtsi +++ b/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_common.dtsi @@ -4,35 +4,44 @@ */ /* Required loopbacks - * P1.8 <-> P1.9 - * P1.10 >-> P1.11 - * P2.8 <-> P2.9 - * P2.10 <-> P1.14 + * P1.8 <-> P1.9 + * P1.10 <-> P1.11 + * P1.12 <-> P1.13 + * P1.14 <-> P2.10 */ / { - aliases { - qdec0 = &qdec20; - qdec1 = &qdec21; - qenca = &phase_a; - qencb = &phase_b; - qenca1 = &phase_a1; - qencb1 = &phase_b1; - }; - encoder-emulate { compatible = "gpio-leds"; - phase_a: phase_a { + + phase_a0: phase_a0 { gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; }; - phase_b: phase_b { + + phase_b0: phase_b0 { gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; }; + phase_a1: phase_a1 { - gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; }; + phase_b1: phase_b1 { - gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; + }; + }; + + qdec_loopbacks: loopbacks { + compatible = "test-qdec-loopbacks"; + + loopback0 { + qdec = <&qdec20>; + qenc-emul-gpios = <&phase_a0 &phase_b0>; + }; + + loopback1 { + qdec = <&qdec21>; + qenc-emul-gpios = <&phase_a1 &phase_b1>; }; }; }; @@ -55,15 +64,15 @@ qdec_21_pinctrl: qdec_21_pinctrl { group1 { - psels = , - ; + psels = , + ; }; }; qdec_21_sleep_pinctrl: qdec_21_sleep_pinctrl { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; @@ -96,3 +105,13 @@ led-pre = <500>; zephyr,pm-device-runtime-auto; }; + +/* To prevent enabling console receiver on cpuapp. */ +&uart20 { + disable-rx; +}; + +/* To prevent enabling console receiver on cpuflpr. */ +&uart30 { + disable-rx; +}; diff --git a/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index 65d42ec40869..68c360fe5eb8 100644 --- a/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -4,8 +4,3 @@ */ #include "nrf54l15dk_nrf54l15_common.dtsi" - -/* To prevent enabling console receiver. */ -&uart20 { - disable-rx; -}; diff --git a/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..6537ce98e293 --- /dev/null +++ b/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,6 @@ +/* + * Copyright 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_common.dtsi" diff --git a/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay b/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay index 76038a2fa012..68c360fe5eb8 100644 --- a/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay +++ b/tests/boards/nrf/qdec/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay @@ -4,8 +4,3 @@ */ #include "nrf54l15dk_nrf54l15_common.dtsi" - -/* To prevent enabling console receiver. */ -&uart30 { - disable-rx; -}; diff --git a/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20_common.dtsi b/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20_common.dtsi index 84e7b1dbc30f..6f8f3a184312 100644 --- a/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20_common.dtsi +++ b/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20_common.dtsi @@ -11,12 +11,6 @@ */ / { - aliases { - qdec0 = &qdec20; - qenca = &phase_a; - qencb = &phase_b; - }; - encoder-emulate { compatible = "gpio-leds"; phase_a: phase_a { @@ -26,6 +20,14 @@ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; }; }; + + qdec_loopbacks: loopbacks { + compatible = "test-qdec-loopbacks"; + loopback0 { + qdec = <&qdec20>; + qenc-emul-gpios = <&phase_a &phase_b>; + }; + }; }; &pinctrl { diff --git a/tests/boards/nrf/qdec/dts/bindings/test-qdec-loopback.yaml b/tests/boards/nrf/qdec/dts/bindings/test-qdec-loopback.yaml new file mode 100644 index 000000000000..e03b2ff3bc32 --- /dev/null +++ b/tests/boards/nrf/qdec/dts/bindings/test-qdec-loopback.yaml @@ -0,0 +1,20 @@ +description: | + Binding describing loopbacks required to run tests/boards/nrf/qdec test in Zephyr. + +compatible: "test-qdec-loopbacks" + +child-binding: + description: | + Binding describing a single loopback pair consisting of a QDEC device and two "gpio-leds" pins + working as a quadrature encoder for the test. + properties: + qdec: + type: phandle + required: true + description: Node of the QDEC device used to capture quadrature signal in the loopback. + qenc-emul-gpios: + type: phandles + required: true + description: | + Children nodes of "gpio-leds" compatible used to generate quadrature signal. The first + phandles outputs phase A signal, the second one outputs phase B signal. diff --git a/tests/boards/nrf/qdec/src/main.c b/tests/boards/nrf/qdec/src/main.c index 7df97be2a432..6bc867f8aa9c 100644 --- a/tests/boards/nrf/qdec/src/main.c +++ b/tests/boards/nrf/qdec/src/main.c @@ -11,27 +11,40 @@ #include #include -static K_SEM_DEFINE(sem, 0, 1); -static const struct gpio_dt_spec phase_a = GPIO_DT_SPEC_GET(DT_ALIAS(qenca), gpios); -static const struct gpio_dt_spec phase_b = GPIO_DT_SPEC_GET(DT_ALIAS(qencb), gpios); -static const struct device *const qdec_dev = DEVICE_DT_GET(DT_ALIAS(qdec0)); -static const uint32_t qdec_config_step = DT_PROP(DT_ALIAS(qdec0), steps); - -/* Disable testing second QDEC instance - * until the issue with multiple - * QDEC instances support is resolved +/** + * Structure grouping gpio pins used for QENC emulation connected with a QDEC device + * with a loopback. */ -#if DT_NODE_EXISTS(DT_ALIAS(qdecX)) -#define SECOND_QDEC_INSTANCE - -static const struct gpio_dt_spec phase_a1 = GPIO_DT_SPEC_GET(DT_ALIAS(qenca1), gpios); -static const struct gpio_dt_spec phase_b1 = GPIO_DT_SPEC_GET(DT_ALIAS(qencb1), gpios); -static const struct device *const qdec_1_dev = DEVICE_DT_GET(DT_ALIAS(qdec1)); -static const uint32_t qdec_1_config_step = DT_PROP(DT_ALIAS(qdec1), steps); -#endif +struct qdec_qenc_loopback { + struct gpio_dt_spec qenc_phase_a; + struct gpio_dt_spec qenc_phase_b; + + const struct device *qdec; + uint32_t qdec_config_step; +}; + +static K_SEM_DEFINE(sem, 0, 1); + +#define GET_QDEC_QENC_LOOPBACK(x) \ + { \ + .qenc_phase_a = GPIO_DT_SPEC_GET(DT_PHANDLE_BY_IDX(x, qenc_emul_gpios, 0), gpios), \ + .qenc_phase_b = GPIO_DT_SPEC_GET(DT_PHANDLE_BY_IDX(x, qenc_emul_gpios, 1), gpios), \ + .qdec = DEVICE_DT_GET(DT_PHANDLE(x, qdec)), \ + .qdec_config_step = DT_PROP_BY_PHANDLE(x, qdec, steps) \ + } + + +struct qdec_qenc_loopback loopbacks[] = { + DT_FOREACH_CHILD_SEP(DT_NODELABEL(qdec_loopbacks), GET_QDEC_QENC_LOOPBACK, (,)) +}; + +#define TESTED_QDEC_COUNT ARRAY_SIZE(loopbacks) + static struct sensor_trigger qdec_trigger = {.type = SENSOR_TRIG_DATA_READY, .chan = SENSOR_CHAN_ROTATION}; + static bool toggle_a = true; +static struct qdec_qenc_loopback *loopback_currently_under_test; static void qdec_trigger_handler(const struct device *dev, const struct sensor_trigger *trigger) { @@ -47,16 +60,15 @@ static void qdec_trigger_handler(const struct device *dev, const struct sensor_t static void qenc_emulate_work_handler(struct k_work *work) { + /* Check if emulation has been stopped after submitting this work item. */ + if (loopback_currently_under_test == NULL) { + return; + } + if (toggle_a) { - gpio_pin_toggle_dt(&phase_a); -#if defined(SECOND_QDEC_INSTANCE) - gpio_pin_toggle_dt(&phase_a1); -#endif + gpio_pin_toggle_dt(&loopback_currently_under_test->qenc_phase_a); } else { - gpio_pin_toggle_dt(&phase_b); -#if defined(SECOND_QDEC_INSTANCE) - gpio_pin_toggle_dt(&phase_b1); -#endif + gpio_pin_toggle_dt(&loopback_currently_under_test->qenc_phase_b); } toggle_a = !toggle_a; } @@ -89,52 +101,48 @@ static void qenc_emulate_setup_pin(const struct gpio_dt_spec *gpio_dt) zassert_true(rc == 0, "%s: pin configure failed: %d", gpio_dt->port->name, rc); } -static void qenc_emulate_start(k_timeout_t period, bool forward) +static void qenc_emulate_start(struct qdec_qenc_loopback *loopback, k_timeout_t period, + bool forward) { - qenc_emulate_reset_pin(&phase_a); - qenc_emulate_reset_pin(&phase_b); -#if defined(SECOND_QDEC_INSTANCE) - qenc_emulate_reset_pin(&phase_a1); - qenc_emulate_reset_pin(&phase_b1); -#endif + qenc_emulate_reset_pin(&loopback->qenc_phase_a); + qenc_emulate_reset_pin(&loopback->qenc_phase_b); toggle_a = !forward; - + loopback_currently_under_test = loopback; k_timer_start(&qenc_emulate_timer, period, period); } static void qenc_emulate_stop(void) { - k_timer_stop(&qenc_emulate_timer); - - qenc_emulate_reset_pin(&phase_a); - qenc_emulate_reset_pin(&phase_b); -#if defined(SECOND_QDEC_INSTANCE) - qenc_emulate_reset_pin(&phase_a1); - qenc_emulate_reset_pin(&phase_b1); -#endif + if (loopback_currently_under_test) { + k_timer_stop(&qenc_emulate_timer); + qenc_emulate_reset_pin(&loopback_currently_under_test->qenc_phase_a); + qenc_emulate_reset_pin(&loopback_currently_under_test->qenc_phase_b); + + loopback_currently_under_test = NULL; + } } -static void qenc_emulate_verify_reading(const struct device *const dev, int emulator_period_ms, - int emulation_duration_ms, bool forward, bool overflow_expected, - const uint32_t config_step) +static void qenc_emulate_verify_reading(struct qdec_qenc_loopback *loopback, + int emulator_period_ms, int emulation_duration_ms, bool forward, + bool overflow_expected) { int rc; struct sensor_value val = {0}; int32_t expected_steps = emulation_duration_ms / emulator_period_ms; - int32_t expected_reading = 360 * expected_steps / config_step; - int32_t delta = expected_reading / 5; + int32_t expected_reading = 360 * expected_steps / loopback->qdec_config_step; + int32_t delta = expected_reading / 4; if (!forward) { expected_reading *= -1; } - qenc_emulate_start(K_MSEC(emulator_period_ms), forward); + qenc_emulate_start(loopback, K_MSEC(emulator_period_ms), forward); /* wait for some readings */ k_msleep(emulation_duration_ms); - rc = sensor_sample_fetch(dev); + rc = sensor_sample_fetch(loopback->qdec); if (!overflow_expected) { zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); @@ -142,7 +150,7 @@ static void qenc_emulate_verify_reading(const struct device *const dev, int emul zassert_true(rc == -EOVERFLOW, "Failed to detect overflow"); } - rc = sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &val); + rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val); zassert_true(rc == 0, "Failed to get sample (%d)", rc); TC_PRINT("Expected reading: %d, actual value: %d, delta: %d\n", @@ -157,31 +165,31 @@ static void qenc_emulate_verify_reading(const struct device *const dev, int emul /* wait and get readings to clear state */ k_msleep(100); - rc = sensor_sample_fetch(dev); + rc = sensor_sample_fetch(loopback->qdec); zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - rc = sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &val); + rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val); zassert_true(rc == 0, "Failed to get sample (%d)", rc); } -static void sensor_trigger_set_and_disable(const struct device *const dev) +static void sensor_trigger_set_and_disable(struct qdec_qenc_loopback *loopback) { int rc; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(dev); + pm_device_runtime_get(loopback->qdec); } k_sem_give(&sem); qdec_trigger.type = SENSOR_TRIG_DATA_READY; qdec_trigger.chan = SENSOR_CHAN_ALL; - rc = sensor_trigger_set(dev, &qdec_trigger, qdec_trigger_handler); + rc = sensor_trigger_set(loopback->qdec, &qdec_trigger, qdec_trigger_handler); zassume_true(rc != -ENOSYS, "sensor_trigger_set not supported"); zassert_true(rc == 0, "sensor_trigger_set failed: %d", rc); - qenc_emulate_start(K_MSEC(10), true); + qenc_emulate_start(loopback, K_MSEC(10), true); /* emulation working, handler should be called */ rc = k_sem_take(&sem, K_MSEC(200)); @@ -193,7 +201,7 @@ static void sensor_trigger_set_and_disable(const struct device *const dev) rc = k_sem_take(&sem, K_MSEC(200)); if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(dev); + pm_device_runtime_put(loopback->qdec); } /* there should be no triggers now*/ @@ -201,22 +209,25 @@ static void sensor_trigger_set_and_disable(const struct device *const dev) zassert_true(rc == -EAGAIN, "qdec handler should not be triggered (%d)", rc); if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(dev); + pm_device_runtime_get(loopback->qdec); } /* register empty trigger - disable trigger */ - rc = sensor_trigger_set(dev, &qdec_trigger, NULL); + rc = sensor_trigger_set(loopback->qdec, &qdec_trigger, NULL); zassert_true(rc == 0, "sensor_trigger_set failed: %d", rc); - qenc_emulate_start(K_MSEC(10), true); + qenc_emulate_start(loopback, K_MSEC(10), true); /* emulation working, but handler not set, thus should not be called */ rc = k_sem_take(&sem, K_MSEC(200)); zassert_true(rc == -EAGAIN, "qdec handler should not be triggered (%d)", rc); if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(dev); + pm_device_runtime_put(loopback->qdec); } + + qenc_emulate_stop(); + k_sem_reset(&sem); } /** @@ -227,49 +238,49 @@ static void sensor_trigger_set_and_disable(const struct device *const dev) */ ZTEST(qdec_sensor, test_sensor_trigger_set_and_disable) { - TC_PRINT("Testing QDEC-0, address: %p\n", qdec_dev); - sensor_trigger_set_and_disable(qdec_dev); -#if defined(SECOND_QDEC_INSTANCE) - TC_PRINT("Testing QDEC-1, address: %p\n", qdec_1_dev); - sensor_trigger_set_and_disable(qdec_1_dev); -#endif - + for (size_t i = 0; i < TESTED_QDEC_COUNT; i++) { + TC_PRINT("Testing QDEC index %d, address: %p\n", i, loopbacks[i].qdec); + sensor_trigger_set_and_disable(&loopbacks[i]); + } } -static void sensor_trigger_set_test(const struct device *const dev) +static void sensor_trigger_set_test(struct qdec_qenc_loopback *loopback) { int rc; struct sensor_value val = {0}; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(dev); + pm_device_runtime_get(loopback->qdec); } qdec_trigger.type = SENSOR_TRIG_DATA_READY; qdec_trigger.chan = SENSOR_CHAN_ROTATION; - rc = sensor_trigger_set(dev, &qdec_trigger, qdec_trigger_handler); + rc = sensor_trigger_set(loopback->qdec, &qdec_trigger, qdec_trigger_handler); zassume_true(rc != -ENOSYS, "sensor_trigger_set not supported"); zassert_true(rc == 0, "sensor_trigger_set failed: %d", rc); - qenc_emulate_start(K_MSEC(10), true); + qenc_emulate_start(loopback, K_MSEC(10), true); /* emulation working now */ rc = k_sem_take(&sem, K_MSEC(200)); zassert_true(rc == 0, "qdec handler should be triggered (%d)", rc); - rc = sensor_sample_fetch(dev); + rc = sensor_sample_fetch(loopback->qdec); zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - rc = sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &val); + rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val); zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); TC_PRINT("QDEC reading: %d\n", val.val1); zassert_true(val.val1 != 0, "No readings from QDEC"); if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(dev); + pm_device_runtime_put(loopback->qdec); } + + qenc_emulate_stop(); + k_sem_reset(&sem); } /** @@ -280,39 +291,37 @@ static void sensor_trigger_set_test(const struct device *const dev) */ ZTEST(qdec_sensor, test_sensor_trigger_set) { - TC_PRINT("Testing QDEC-0, address: %p\n", qdec_dev); - sensor_trigger_set_test(qdec_dev); -#if defined(SECOND_QDEC_INSTANCE) - TC_PRINT("Testing QDEC-1, address: %p\n", qdec_1_dev); - sensor_trigger_set_test(qdec_1_dev); -#endif + for (size_t i = 0; i < TESTED_QDEC_COUNT; i++) { + TC_PRINT("Testing QDEC index %d, address: %p\n", i, loopbacks[i].qdec); + sensor_trigger_set_test(&loopbacks[i]); + } } -static void sensor_trigger_set_negative(const struct device *const dev) +static void sensor_trigger_set_negative(struct qdec_qenc_loopback *loopback) { int rc; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(dev); + pm_device_runtime_get(loopback->qdec); } - rc = sensor_trigger_set(dev, &qdec_trigger, qdec_trigger_handler); + rc = sensor_trigger_set(loopback->qdec, &qdec_trigger, qdec_trigger_handler); zassume_true(rc != -ENOSYS, "sensor_trigger_set not supported"); qdec_trigger.type = SENSOR_TRIG_MAX; qdec_trigger.chan = SENSOR_CHAN_ROTATION; - rc = sensor_trigger_set(dev, &qdec_trigger, qdec_trigger_handler); + rc = sensor_trigger_set(loopback->qdec, &qdec_trigger, qdec_trigger_handler); zassume_true(rc < 0, "sensor_trigger_set should fail due to invalid trigger type"); qdec_trigger.type = SENSOR_TRIG_DATA_READY; qdec_trigger.chan = SENSOR_CHAN_MAX; - rc = sensor_trigger_set(dev, &qdec_trigger, qdec_trigger_handler); + rc = sensor_trigger_set(loopback->qdec, &qdec_trigger, qdec_trigger_handler); zassume_true(rc < 0, "sensor_trigger_set should fail due to invalid channel"); if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(dev); + pm_device_runtime_put(loopback->qdec); } } @@ -324,12 +333,10 @@ static void sensor_trigger_set_negative(const struct device *const dev) */ ZTEST(qdec_sensor, test_sensor_trigger_set_negative) { - TC_PRINT("Testing QDEC-0, address: %p\n", qdec_dev); - sensor_trigger_set_negative(qdec_dev); -#if defined(SECOND_QDEC_INSTANCE) - TC_PRINT("Testing QDEC-1, address: %p\n", qdec_1_dev); - sensor_trigger_set_negative(qdec_1_dev); -#endif + for (size_t i = 0; i < TESTED_QDEC_COUNT; i++) { + TC_PRINT("Testing QDEC index %d, address: %p\n", i, loopbacks[i].qdec); + sensor_trigger_set_negative(&loopbacks[i]); + } } /** @@ -340,37 +347,22 @@ ZTEST(qdec_sensor, test_sensor_trigger_set_negative) */ ZTEST(qdec_sensor, test_qdec_readings) { - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(qdec_dev); + for (size_t i = 0; i < TESTED_QDEC_COUNT; i++) { + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + pm_device_runtime_get(loopbacks[i].qdec); + } + + TC_PRINT("Testing QDEC index %d, address: %p\n", i, loopbacks[i].qdec); + qenc_emulate_verify_reading(&loopbacks[i], 10, 100, true, false); + qenc_emulate_verify_reading(&loopbacks[i], 2, 500, true, false); + qenc_emulate_verify_reading(&loopbacks[i], 10, 200, false, false); + qenc_emulate_verify_reading(&loopbacks[i], 1, 1000, false, true); + qenc_emulate_verify_reading(&loopbacks[i], 1, 1000, true, true); + + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + pm_device_runtime_put(loopbacks[i].qdec); + } } - - TC_PRINT("Testing QDEC-0, address: %p\n", qdec_dev); - qenc_emulate_verify_reading(qdec_dev, 10, 100, true, false, qdec_config_step); - qenc_emulate_verify_reading(qdec_dev, 2, 500, true, false, qdec_config_step); - qenc_emulate_verify_reading(qdec_dev, 10, 200, false, false, qdec_config_step); - qenc_emulate_verify_reading(qdec_dev, 1, 1000, false, true, qdec_config_step); - qenc_emulate_verify_reading(qdec_dev, 1, 1000, true, true, qdec_config_step); - - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(qdec_dev); - } - -#if defined(SECOND_QDEC_INSTANCE) - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(qdec_1_dev); - } - - TC_PRINT("Testing QDEC-1, address: %p\n", qdec_1_dev); - qenc_emulate_verify_reading(qdec_1_dev, 10, 100, true, false, qdec_1_config_step); - qenc_emulate_verify_reading(qdec_1_dev, 2, 500, true, false, qdec_1_config_step); - qenc_emulate_verify_reading(qdec_1_dev, 10, 200, false, false, qdec_1_config_step); - qenc_emulate_verify_reading(qdec_1_dev, 1, 1000, false, true, qdec_1_config_step); - qenc_emulate_verify_reading(qdec_1_dev, 1, 1000, true, true, qdec_1_config_step); - - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(qdec_1_dev); - } -#endif } static void sensor_channel_get_empty(const struct device *const dev) @@ -419,40 +411,38 @@ static void sensor_channel_get_empty(const struct device *const dev) */ ZTEST(qdec_sensor, test_sensor_channel_get_empty) { - TC_PRINT("Testing QDEC-0, address: %p\n", qdec_dev); - sensor_channel_get_empty(qdec_dev); -#if defined(SECOND_QDEC_INSTANCE) - TC_PRINT("Testing QDEC-1, address: %p\n", qdec_1_dev); - sensor_channel_get_empty(qdec_1_dev); -#endif + for (size_t i = 0; i < TESTED_QDEC_COUNT; i++) { + TC_PRINT("Testing QDEC index %d, address: %p\n", i, loopbacks[i].qdec); + sensor_channel_get_empty(loopbacks[i].qdec); + } } -static void sensor_channel_get_test(const struct device *const dev) +static void sensor_channel_get_test(struct qdec_qenc_loopback *loopback) { int rc; struct sensor_value val_first = {0}; struct sensor_value val_second = {0}; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(qdec_dev); + pm_device_runtime_get(loopback->qdec); } - qenc_emulate_start(K_MSEC(10), true); + qenc_emulate_start(loopback, K_MSEC(10), true); /* wait for some readings*/ k_msleep(100); - rc = sensor_sample_fetch(qdec_dev); + rc = sensor_sample_fetch(loopback->qdec); zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val_first); + rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val_first); zassert_true(rc == 0, "Failed to get sample (%d)", rc); zassert_true(val_first.val1 != 0, "No readings from QDEC"); /* wait for more readings*/ k_msleep(200); - rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val_second); + rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_ROTATION, &val_second); zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); zassert_true(val_second.val1 != 0, "No readings from QDEC"); @@ -470,7 +460,7 @@ static void sensor_channel_get_test(const struct device *const dev) val_second.val2); if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(qdec_dev); + pm_device_runtime_put(loopback->qdec); } } @@ -482,38 +472,36 @@ static void sensor_channel_get_test(const struct device *const dev) */ ZTEST(qdec_sensor, test_sensor_channel_get) { - TC_PRINT("Testing QDEC-0, address: %p\n", qdec_dev); - sensor_channel_get_test(qdec_dev); -#if defined(SECOND_QDEC_INSTANCE) - TC_PRINT("Testing QDEC-1, address: %p\n", qdec_1_dev); - sensor_channel_get_test(qdec_1_dev); -#endif + for (size_t i = 0; i < TESTED_QDEC_COUNT; i++) { + TC_PRINT("Testing QDEC index %d, address: %p\n", i, loopbacks[i].qdec); + sensor_channel_get_test(&loopbacks[i]); + } } -static void sensor_channel_get_negative(const struct device *const dev) +static void sensor_channel_get_negative(struct qdec_qenc_loopback *loopback) { int rc; struct sensor_value val = {0}; if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(dev); + pm_device_runtime_get(loopback->qdec); } - qenc_emulate_start(K_MSEC(10), true); + qenc_emulate_start(loopback, K_MSEC(10), true); /* wait for some readings*/ k_msleep(100); - rc = sensor_sample_fetch(dev); + rc = sensor_sample_fetch(loopback->qdec); zassert_true(rc == 0, "Failed to fetch sample (%d)", rc); - rc = sensor_channel_get(dev, SENSOR_CHAN_MAX, &val); + rc = sensor_channel_get(loopback->qdec, SENSOR_CHAN_MAX, &val); zassert_true(rc < 0, "Should failed to get sample (%d)", rc); zassert_true(val.val1 == 0, "Some readings from QDEC: %d", val.val1); zassert_true(val.val2 == 0, "Some readings from QDEC: %d", val.val2); if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(dev); + pm_device_runtime_put(loopback->qdec); } } @@ -525,12 +513,10 @@ static void sensor_channel_get_negative(const struct device *const dev) */ ZTEST(qdec_sensor, test_sensor_channel_get_negative) { - TC_PRINT("Testing QDEC-0, address: %p\n", qdec_dev); - sensor_channel_get_negative(qdec_dev); -#if defined(SECOND_QDEC_INSTANCE) - TC_PRINT("Testing QDEC-1, address: %p\n", qdec_1_dev); - sensor_channel_get_negative(qdec_1_dev); -#endif + for (size_t i = 0; i < TESTED_QDEC_COUNT; i++) { + TC_PRINT("Testing QDEC index %d, address: %p\n", i, loopbacks[i].qdec); + sensor_channel_get_negative(&loopbacks[i]); + } } static void sensor_sample_fetch_test(const struct device *const dev) @@ -563,32 +549,22 @@ static void sensor_sample_fetch_test(const struct device *const dev) */ ZTEST(qdec_sensor, test_sensor_sample_fetch) { - TC_PRINT("Testing QDEC-0, address: %p\n", qdec_dev); - sensor_sample_fetch_test(qdec_dev); -#if defined(SECOND_QDEC_INSTANCE) - TC_PRINT("Testing QDEC-1, address: %p\n", qdec_1_dev); - sensor_sample_fetch_test(qdec_1_dev); -#endif + for (size_t i = 0; i < TESTED_QDEC_COUNT; i++) { + TC_PRINT("Testing QDEC index %d, address: %p\n", i, loopbacks[i].qdec); + sensor_sample_fetch_test(loopbacks[i].qdec); + } } static void *setup(void) { - int rc; - - rc = device_is_ready(qdec_dev); - zassert_true(rc, "QDEC device not ready: %d", rc); + for (size_t i = 0; i < TESTED_QDEC_COUNT; i++) { + int rc = device_is_ready(loopbacks[i].qdec); - qenc_emulate_setup_pin(&phase_a); - qenc_emulate_setup_pin(&phase_b); - -#if defined(SECOND_QDEC_INSTANCE) - rc = device_is_ready(qdec_1_dev); - zassert_true(rc, "QDEC 1 device not ready: %d", rc); - - qenc_emulate_setup_pin(&phase_a1); - qenc_emulate_setup_pin(&phase_b1); -#endif + zassert_true(rc, "QDEC index %d not ready: %d", i, rc); + qenc_emulate_setup_pin(&loopbacks[i].qenc_phase_a); + qenc_emulate_setup_pin(&loopbacks[i].qenc_phase_b); + } return NULL; } @@ -604,6 +580,7 @@ static void after(void *fixture) ARG_UNUSED(fixture); qenc_emulate_stop(); + k_sem_reset(&sem); } ZTEST_SUITE(qdec_sensor, NULL, setup, before, after, NULL); diff --git a/tests/boards/nrf/qdec/testcase.yaml b/tests/boards/nrf/qdec/testcase.yaml index 2908a68a6d14..e3eb262685ad 100644 --- a/tests/boards/nrf/qdec/testcase.yaml +++ b/tests/boards/nrf/qdec/testcase.yaml @@ -5,6 +5,7 @@ common: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - nrf54l15dk/nrf54l15/cpuflpr + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - nrf54lm20dk/nrf54lm20a/cpuflpr integration_platforms: diff --git a/tests/boot/mcuboot_recovery_retention/sysbuild.conf b/tests/boot/mcuboot_recovery_retention/sysbuild.conf index 47f00ff3cff8..3b5b3c963800 100644 --- a/tests/boot/mcuboot_recovery_retention/sysbuild.conf +++ b/tests/boot/mcuboot_recovery_retention/sysbuild.conf @@ -1 +1,2 @@ SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/boot/test_mcuboot/sysbuild.cmake b/tests/boot/test_mcuboot/sysbuild.cmake index dc5165114b58..920d07933917 100644 --- a/tests/boot/test_mcuboot/sysbuild.cmake +++ b/tests/boot/test_mcuboot/sysbuild.cmake @@ -14,6 +14,12 @@ ExternalZephyrProject_Add( SOURCE_DIR ${APP_DIR}/swapped_app ) +# This section ensures that sysbuild-related configurations, such as the MCUBOOT swap type, +# are passed down to the swapped_app image. +set_target_properties(swapped_app PROPERTIES + IMAGE_CONF_SCRIPT ${ZEPHYR_BASE}/share/sysbuild/image_configurations/MAIN_image_default.cmake +) + # Add the swapped app to the list of images to flash # Ensure the flashing order of images is as follows: # - mcuboot diff --git a/tests/boot/test_mcuboot/sysbuild.conf b/tests/boot/test_mcuboot/sysbuild.conf index 47f00ff3cff8..3b5b3c963800 100644 --- a/tests/boot/test_mcuboot/sysbuild.conf +++ b/tests/boot/test_mcuboot/sysbuild.conf @@ -1 +1,2 @@ SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/bsim/bluetooth/audio/src/common.c b/tests/bsim/bluetooth/audio/src/common.c index 29e8c5cc2379..d09bcacd3797 100644 --- a/tests/bsim/bluetooth/audio/src/common.c +++ b/tests/bsim/bluetooth/audio/src/common.c @@ -264,20 +264,20 @@ void start_broadcast_adv(struct bt_le_ext_adv *adv) return; } - if (info.ext_adv_state == BT_LE_EXT_ADV_STATE_DISABLED) { - /* Start extended advertising */ - err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + if (info.per_adv_state == BT_LE_PER_ADV_STATE_DISABLED) { + /* Enable Periodic Advertising */ + err = bt_le_per_adv_start(adv); if (err != 0) { - FAIL("Failed to start extended advertising: %d\n", err); + FAIL("Failed to enable periodic advertising: %d\n", err); return; } } - if (info.per_adv_state == BT_LE_PER_ADV_STATE_DISABLED) { - /* Enable Periodic Advertising */ - err = bt_le_per_adv_start(adv); + if (info.ext_adv_state == BT_LE_EXT_ADV_STATE_DISABLED) { + /* Start extended advertising */ + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); if (err != 0) { - FAIL("Failed to enable periodic advertising: %d\n", err); + FAIL("Failed to start extended advertising: %d\n", err); return; } } diff --git a/tests/bsim/bluetooth/compile.nrf54l15bsim_nrf54l15_cpuapp.sh b/tests/bsim/bluetooth/compile.nrf54l15bsim_nrf54l15_cpuapp.sh index 9db8bbcf8d25..ee428e1a97ce 100755 --- a/tests/bsim/bluetooth/compile.nrf54l15bsim_nrf54l15_cpuapp.sh +++ b/tests/bsim/bluetooth/compile.nrf54l15bsim_nrf54l15_cpuapp.sh @@ -13,6 +13,11 @@ export BOARD="${BOARD:-nrf54l15bsim/nrf54l15/cpuapp}" source ${ZEPHYR_BASE}/tests/bsim/compile.source +app=tests/bsim/bluetooth/ll/advx compile +app=tests/bsim/bluetooth/ll/advx conf_overlay=overlay-ticker_expire_info.conf compile +app=tests/bsim/bluetooth/ll/advx conf_overlay=overlay-scan_aux_use_chains.conf compile +app=tests/bsim/bluetooth/ll/conn conf_file=prj_split.conf compile +app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_privacy.conf compile app=tests/bsim/bluetooth/ll/throughput compile app=tests/bsim/bluetooth/ll/throughput conf_overlay=overlay-no_phy_update.conf compile app=tests/bsim/bluetooth/ll/multiple_id compile diff --git a/tests/bsim/bluetooth/host/gatt/caching/psa_overlay.conf b/tests/bsim/bluetooth/host/gatt/caching/psa_overlay.conf index b836ab2c23b2..bc7c220f62f6 100644 --- a/tests/bsim/bluetooth/host/gatt/caching/psa_overlay.conf +++ b/tests/bsim/bluetooth/host/gatt/caching/psa_overlay.conf @@ -1,3 +1,2 @@ -CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_CRYPTO=y CONFIG_PSA_CRYPTO_ENABLE_ALL=y diff --git a/tests/bsim/bluetooth/ll/advx/src/main.c b/tests/bsim/bluetooth/ll/advx/src/main.c index cd9f0a4cd503..ac9d99976c55 100644 --- a/tests/bsim/bluetooth/ll/advx/src/main.c +++ b/tests/bsim/bluetooth/ll/advx/src/main.c @@ -29,7 +29,11 @@ #define EVT_PROP_TXP BIT(6) #define ADV_INTERVAL 0x20 /* 20 ms advertising interval */ #define ADV_WAIT_MS 10 /* 10 ms wait loop */ +#if defined(CONFIG_BT_CTLR_PRIVACY) +#define OWN_ADDR_TYPE BT_HCI_OWN_ADDR_RPA_OR_RANDOM +#else /* !CONFIG_BT_CTLR_PRIVACY */ #define OWN_ADDR_TYPE BT_HCI_OWN_ADDR_RANDOM +#endif /* !CONFIG_BT_CTLR_PRIVACY */ #define PEER_ADDR_TYPE BT_HCI_OWN_ADDR_RANDOM #define PEER_ADDR peer_addr #define ADV_CHAN_MAP 0x07 @@ -675,28 +679,32 @@ static void test_advx_main(void) k_sleep(K_MSEC(1000)); - printk("Add to resolving list..."); - bt_addr_le_t peer_id_addr = { - .type = BT_ADDR_LE_RANDOM, - .a = { - .val = {0xc6, 0xc7, 0xc8, 0xc9, 0xc1, 0xcb} - } - }; - uint8_t pirk[16] = {0x00, }; - uint8_t lirk[16] = {0x01, }; + if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY)) { + printk("Add to resolving list..."); + bt_addr_le_t peer_id_addr = { + .type = BT_ADDR_LE_RANDOM, + .a = { + .val = {0xc6, 0xc7, 0xc8, 0xc9, 0xc1, 0xcb} + } + }; + uint8_t pirk[16] = {0xAB, 0xBA, 0xAB, 0xBA, 0xAB, 0xBA, 0xAB, 0xBA, + 0xAB, 0xBA, 0xAB, 0xBA, 0xAB, 0xBA, 0xAB, 0xBA}; + uint8_t lirk[16] = {0x12, 0x21, 0x12, 0x21, 0x12, 0x21, 0x12, 0x21, + 0x12, 0x21, 0x12, 0x21, 0x12, 0x21, 0x12, 0x21}; - err = ll_rl_add(&peer_id_addr, pirk, lirk); - if (err) { - goto exit; - } - printk("success.\n"); + err = ll_rl_add(&peer_id_addr, pirk, lirk); + if (err) { + goto exit; + } + printk("success.\n"); - printk("Enable resolving list..."); - err = ll_rl_enable(BT_HCI_ADDR_RES_ENABLE); - if (err) { - goto exit; + printk("Enable resolving list..."); + err = ll_rl_enable(BT_HCI_ADDR_RES_ENABLE); + if (err) { + goto exit; + } + printk("success.\n"); } - printk("success.\n"); printk("Enabling extended..."); err = ll_adv_enable(handle, 1, 0, 0); @@ -1716,28 +1724,46 @@ static void test_scanx_main(void) } printk("done.\n"); - printk("Add to resolving list..."); bt_addr_le_t peer_id_addr = { .type = BT_ADDR_LE_RANDOM, .a = { .val = {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5} } }; - uint8_t pirk[16] = {0x01, }; - uint8_t lirk[16] = {0x00, }; - err = ll_rl_add(&peer_id_addr, pirk, lirk); - if (err) { - goto exit; - } - printk("success.\n"); + if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY)) { + printk("Add to resolving list..."); + bt_addr_le_t some_id_addr = { + .type = BT_ADDR_LE_RANDOM, + .a = { + .val = {0x78, 0x87, 0x78, 0x87, 0x78, 0x87} + } + }; + uint8_t pirk[16] = {0x12, 0x21, 0x12, 0x21, 0x12, 0x21, 0x12, 0x21, + 0x12, 0x21, 0x12, 0x21, 0x12, 0x21, 0x12, 0x21}; + uint8_t lirk[16] = {0xCD, 0xDC, 0xCD, 0xDC, 0xCD, 0xDC, 0xCD, 0xDC, + 0xCD, 0xDC, 0xCD, 0xDC, 0xCD, 0xDC, 0xCD, 0xDC}; + + /* some_id_addr with swapped peer IRK and local IRK */ + err = ll_rl_add(&some_id_addr, lirk, pirk); + if (err) { + goto exit; + } - printk("Enable resolving list..."); - err = ll_rl_enable(BT_HCI_ADDR_RES_ENABLE); - if (err) { - goto exit; + /* peer_id_addr with correct peer IRK and local IRK */ + err = ll_rl_add(&peer_id_addr, pirk, lirk); + if (err) { + goto exit; + } + printk("success.\n"); + + printk("Enable resolving list..."); + err = ll_rl_enable(BT_HCI_ADDR_RES_ENABLE); + if (err) { + goto exit; + } + printk("success.\n"); } - printk("success.\n"); printk("Add device to periodic advertising list..."); err = bt_le_per_adv_list_add(&peer_id_addr, per_sid); diff --git a/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx.sh b/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx.sh index 540611f69a37..02add45e85eb 100755 --- a/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx.sh +++ b/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx.sh @@ -13,10 +13,10 @@ EXECUTE_TIMEOUT=120 cd ${BSIM_OUT_PATH}/bin Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_advx_prj_conf \ - -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=advx + -v=${verbosity_level} -s=${simulation_id} -RealEncryption=1 -d=0 -testid=advx Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_advx_prj_conf\ - -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=scanx + -v=${verbosity_level} -s=${simulation_id} -RealEncryption=1 -d=1 -testid=scanx Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=60e6 $@ diff --git a/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx_scan_aux_use_chains.sh b/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx_scan_aux_use_chains.sh index 0e26ae907de3..0331788a6309 100755 --- a/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx_scan_aux_use_chains.sh +++ b/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx_scan_aux_use_chains.sh @@ -13,10 +13,10 @@ EXECUTE_TIMEOUT=120 cd ${BSIM_OUT_PATH}/bin Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_advx_prj_conf_overlay-scan_aux_use_chains_conf \ - -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=advx + -v=${verbosity_level} -s=${simulation_id} -RealEncryption=1 -d=0 -testid=advx Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_advx_prj_conf_overlay-scan_aux_use_chains_conf \ - -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=scanx + -v=${verbosity_level} -s=${simulation_id} -RealEncryption=1 -d=1 -testid=scanx Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=60e6 $@ diff --git a/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx_ticker_expire_info.sh b/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx_ticker_expire_info.sh index cabee84f0157..655732639171 100755 --- a/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx_ticker_expire_info.sh +++ b/tests/bsim/bluetooth/ll/advx/tests_scripts/basic_advx_ticker_expire_info.sh @@ -13,10 +13,10 @@ EXECUTE_TIMEOUT=120 cd ${BSIM_OUT_PATH}/bin Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_advx_prj_conf_overlay-ticker_expire_info_conf \ - -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=advx + -v=${verbosity_level} -s=${simulation_id} -RealEncryption=1 -d=0 -testid=advx Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_advx_prj_conf_overlay-ticker_expire_info_conf \ - -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=scanx + -v=${verbosity_level} -s=${simulation_id} -RealEncryption=1 -d=1 -testid=scanx Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ -D=2 -sim_length=60e6 $@ diff --git a/tests/bsim/bluetooth/ll/conn/psa_overlay.conf b/tests/bsim/bluetooth/ll/conn/psa_overlay.conf index b836ab2c23b2..bc7c220f62f6 100644 --- a/tests/bsim/bluetooth/ll/conn/psa_overlay.conf +++ b/tests/bsim/bluetooth/ll/conn/psa_overlay.conf @@ -1,3 +1,2 @@ -CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_CRYPTO=y CONFIG_PSA_CRYPTO_ENABLE_ALL=y diff --git a/tests/bsim/bluetooth/mesh/src/test_provision.c b/tests/bsim/bluetooth/mesh/src/test_provision.c index 321d168914fd..a93add213907 100644 --- a/tests/bsim/bluetooth/mesh/src/test_provision.c +++ b/tests/bsim/bluetooth/mesh/src/test_provision.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Lingao Meng + * Copyright (c) 2025 Nordic Semiconductor * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,12 +10,11 @@ #include "mesh/access.h" #include "mesh/net.h" #include "mesh/crypto.h" +#include "mesh/prov.h" #include "argparse.h" #include #include -#include - #include #define LOG_MODULE_NAME mesh_prov @@ -65,15 +65,19 @@ static struct oob_auth_test_vector_s { {static_key1, sizeof(static_key1), 0, 0, 0, 0}, {static_key2, sizeof(static_key2), 0, 0, 0, 0}, {static_key3, sizeof(static_key3), 0, 0, 0, 0}, - {NULL, 0, 3, BT_MESH_BLINK, 0, 0}, + {NULL, 0, 1, BT_MESH_BLINK, 0, 0}, {NULL, 0, 5, BT_MESH_BEEP, 0, 0}, - {NULL, 0, 6, BT_MESH_VIBRATE, 0, 0}, - {NULL, 0, 7, BT_MESH_DISPLAY_NUMBER, 0, 0}, - {NULL, 0, 8, BT_MESH_DISPLAY_STRING, 0, 0}, - {NULL, 0, 0, 0, 4, BT_MESH_PUSH}, + {NULL, 0, 8, BT_MESH_VIBRATE, 0, 0}, + {NULL, 0, 15, BT_MESH_DISPLAY_NUMBER, 0, 0}, + {NULL, 0, 19, BT_MESH_DISPLAY_STRING, 0, 0}, + {NULL, 0, 32, BT_MESH_DISPLAY_NUMBER, 0, 0}, + {NULL, 0, 32, BT_MESH_DISPLAY_STRING, 0, 0}, + {NULL, 0, 0, 0, 1, BT_MESH_PUSH}, {NULL, 0, 0, 0, 5, BT_MESH_TWIST}, - {NULL, 0, 0, 0, 8, BT_MESH_ENTER_NUMBER}, - {NULL, 0, 0, 0, 7, BT_MESH_ENTER_STRING}, + {NULL, 0, 0, 0, 13, BT_MESH_ENTER_NUMBER}, + {NULL, 0, 0, 0, 27, BT_MESH_ENTER_STRING}, + {NULL, 0, 0, 0, 32, BT_MESH_ENTER_NUMBER}, + {NULL, 0, 0, 0, 32, BT_MESH_ENTER_STRING}, }; static ATOMIC_DEFINE(test_flags, TEST_FLAGS); @@ -414,25 +418,23 @@ static int input(bt_mesh_input_action_t act, uint8_t size) static void delayed_input(struct k_work *work) { - char oob_str[16]; - uint32_t oob_number; + uint8_t oob_data[PROV_IO_OOB_SIZE_MAX + 1] = {0}; int size = bs_bc_is_msg_received(*oob_channel_id); - if (size <= 0) { - FAIL("OOB data is not gotten"); - } + ASSERT_TRUE_MSG(size > 0, "OOB data is not gotten"); + ASSERT_TRUE_MSG(size <= PROV_IO_OOB_SIZE_MAX, "OOB data size %d exceeds max %d", + size, PROV_IO_OOB_SIZE_MAX); + + bs_bc_receive_msg(*oob_channel_id, oob_data, size); switch (gact) { case BT_MESH_PUSH: case BT_MESH_TWIST: case BT_MESH_ENTER_NUMBER: - ASSERT_TRUE(size == sizeof(uint32_t)); - bs_bc_receive_msg(*oob_channel_id, (uint8_t *)&oob_number, size); - ASSERT_OK(bt_mesh_input_number(oob_number)); + ASSERT_OK(bt_mesh_input_numeric(oob_data, size)); break; case BT_MESH_ENTER_STRING: - bs_bc_receive_msg(*oob_channel_id, (uint8_t *)oob_str, size); - ASSERT_OK(bt_mesh_input_string(oob_str)); + ASSERT_OK(bt_mesh_input_string((const char *)oob_data)); break; default: FAIL("Unknown input action %u (size %u) requested!", gact, gsize); @@ -444,7 +446,7 @@ static void prov_input_complete(void) LOG_INF("Input OOB data completed"); } -static int output_number(bt_mesh_output_action_t action, uint32_t number); +static int output_numeric(bt_mesh_output_action_t act, uint8_t *numeric, size_t size); static int output_string(const char *str); static void capabilities(const struct bt_mesh_dev_capabilities *cap); static struct bt_mesh_prov prov = { @@ -456,7 +458,7 @@ static struct bt_mesh_prov prov = { .link_close = prov_link_close, .reprovisioned = prov_reprovisioned, .node_added = prov_node_added, - .output_number = output_number, + .output_numeric = output_numeric, .output_string = output_string, .input = input, .input_complete = prov_input_complete, @@ -464,11 +466,48 @@ static struct bt_mesh_prov prov = { .reset = prov_reset, }; -static int output_number(bt_mesh_output_action_t action, uint32_t number) +static void binary_to_ascii_digits(const uint8_t *in, size_t in_len, char *out_str) +{ + uint8_t temp[PROV_IO_OOB_SIZE_MAX]; + size_t digit_count = 0; + + memcpy(temp, in, in_len); + + while (in_len > 0) { + uint16_t remainder = 0; + + /* Divide the number in `temp` by 10, store quotient back in `temp` */ + for (ssize_t i = in_len - 1; i >= 0; --i) { + uint16_t acc = ((uint16_t)remainder << 8) | temp[i]; + + temp[i] = acc / 10; + remainder = acc % 10; + } + + /* Store ASCII digit */ + out_str[digit_count++] = '0' + remainder; + + /* Trim leading zeros */ + while (in_len > 0 && temp[in_len - 1] == 0) { + in_len--; + } + } + + /* Digits are in reverse order, reverse them to get correct string */ + sys_mem_swap(out_str, digit_count); + + /* Null-terminate the string */ + out_str[digit_count] = '\0'; +} + +static int output_numeric(bt_mesh_output_action_t act, uint8_t *numeric, size_t size) { - LOG_INF("OOB Number: %u", number); + uint8_t numeric_ascii[PROV_IO_OOB_SIZE_MAX + 1]; + + binary_to_ascii_digits(numeric, size, numeric_ascii); + LOG_INF("OOB Number: %s", numeric_ascii); - bs_bc_send_msg(*oob_channel_id, (uint8_t *)&number, sizeof(uint32_t)); + bs_bc_send_msg(*oob_channel_id, numeric, size); return 0; } @@ -476,7 +515,7 @@ static int output_string(const char *str) { LOG_INF("OOB String: %s", str); - bs_bc_send_msg(*oob_channel_id, (uint8_t *)str, strlen(str) + 1); + bs_bc_send_msg(*oob_channel_id, (uint8_t *)str, strlen(str)); return 0; } diff --git a/tests/bsim/bluetooth/tester/src/audio/vcp_peripheral.c b/tests/bsim/bluetooth/tester/src/audio/vcp_peripheral.c index 9fdfbcaf50ef..ef5a0efc2f1d 100644 --- a/tests/bsim/bluetooth/tester/src/audio/vcp_peripheral.c +++ b/tests/bsim/bluetooth/tester/src/audio/vcp_peripheral.c @@ -35,6 +35,7 @@ static void test_vcp_peripheral(void) bsim_btp_core_register(BTP_SERVICE_ID_AICS); bsim_btp_gap_set_discoverable(BTP_GAP_GENERAL_DISCOVERABLE); + bsim_btp_vcs_register(1U, 0U, 100U); bsim_btp_gap_start_advertising(0U, 0U, NULL, BT_HCI_OWN_ADDR_PUBLIC); bsim_btp_wait_for_gap_device_connected(&remote_addr); bt_addr_le_to_str(&remote_addr, addr_str, sizeof(addr_str)); diff --git a/tests/bsim/bluetooth/tester/src/bsim_btp.c b/tests/bsim/bluetooth/tester/src/bsim_btp.c index a5b2c7000dc8..2e24514b6606 100644 --- a/tests/bsim/bluetooth/tester/src/bsim_btp.c +++ b/tests/bsim/bluetooth/tester/src/bsim_btp.c @@ -873,6 +873,8 @@ static bool is_valid_vcs_packet_len(const struct btp_hdr *hdr, struct net_buf_si return buf_simple->len == 0U; case BTP_VCS_UNMUTE: return buf_simple->len == 0U; + case BTP_VCS_REGISTER: + return buf_simple->len == 0U; /* no events */ default: @@ -1236,7 +1238,7 @@ static bool is_valid_csis_packet_len(const struct btp_hdr *hdr, struct net_buf_s return buf_simple->len == 0U; case BTP_CSIS_GET_MEMBER_RSI: return buf_simple->len == sizeof(struct btp_csis_get_member_rsi_rp); - case BTP_CSIS_ENC_SIRK_TYPE: + case BTP_CSIS_SET_SIRK_TYPE: return buf_simple->len == 0U; /* No events */ diff --git a/tests/bsim/bluetooth/tester/src/bsim_btp.h b/tests/bsim/bluetooth/tester/src/bsim_btp.h index 75198bf498eb..2480076bc069 100644 --- a/tests/bsim/bluetooth/tester/src/bsim_btp.h +++ b/tests/bsim/bluetooth/tester/src/bsim_btp.h @@ -563,6 +563,27 @@ static inline void bsim_btp_wait_for_tmap_discovery_complete(void) net_buf_unref(buf); } +static inline void bsim_btp_vcs_register(uint8_t step, uint8_t flags, uint8_t vol) +{ + struct btp_vcs_register_cmd *cmd; + struct btp_hdr *cmd_hdr; + + NET_BUF_SIMPLE_DEFINE(cmd_buffer, BTP_MTU); + + cmd_hdr = net_buf_simple_add(&cmd_buffer, sizeof(*cmd_hdr)); + cmd_hdr->service = BTP_SERVICE_ID_VCS; + cmd_hdr->opcode = BTP_VCS_REGISTER; + cmd_hdr->index = BTP_INDEX; + cmd = net_buf_simple_add(&cmd_buffer, sizeof(*cmd)); + cmd->step = step; + cmd->flags = flags; + cmd->volume = vol; + + cmd_hdr->len = sys_cpu_to_le16(cmd_buffer.len - sizeof(*cmd_hdr)); + + bsim_btp_send_to_tester(cmd_buffer.data, cmd_buffer.len); +} + static inline void bsim_btp_vcp_discover(const bt_addr_le_t *address) { struct btp_vcp_discover_cmd *cmd; diff --git a/tests/bsim/bluetooth/tests.nrf54l15bsim_nrf54l15_cpuapp.txt b/tests/bsim/bluetooth/tests.nrf54l15bsim_nrf54l15_cpuapp.txt index d5dee727d5e9..d289755e9fb3 100644 --- a/tests/bsim/bluetooth/tests.nrf54l15bsim_nrf54l15_cpuapp.txt +++ b/tests/bsim/bluetooth/tests.nrf54l15bsim_nrf54l15_cpuapp.txt @@ -1,5 +1,8 @@ # Search paths(s) for tests which will be run in the nrf54l15 app core # This file is used in CI to select which tests are run +tests/bsim/bluetooth/ll/advx/ +tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_encrypted_split.sh +tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_encrypted_split_privacy.sh tests/bsim/bluetooth/ll/throughput/ tests/bsim/bluetooth/ll/multiple_id/ tests/bsim/bluetooth/ll/bis/tests_scripts/broadcast_iso_interleaved.sh diff --git a/tests/crypto/mbedtls/CMakeLists.txt b/tests/crypto/mbedtls/CMakeLists.txt index 7ebdc9d76a9a..47670bead010 100644 --- a/tests/crypto/mbedtls/CMakeLists.txt +++ b/tests/crypto/mbedtls/CMakeLists.txt @@ -6,15 +6,5 @@ project(mbedtls) set(output_file ${PROJECT_BINARY_DIR}/mbedtls-check.timestamp) -add_custom_command( - COMMENT "Check Mbed TLS auto-generated files" - COMMAND - ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/modules/mbedtls/create_psa_files.py --check - OUTPUT - ${output_file} -) - -add_custom_target(check_mbedtls_auto_generated_files ALL DEPENDS ${output_file}) - FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/tests/crypto/mbedtls_psa/boards/nrf54l05dk_nrf54l05_cpuapp.conf b/tests/crypto/mbedtls_psa/boards/nrf54l05dk_nrf54l05_cpuapp.conf new file mode 100644 index 000000000000..70c601183ddf --- /dev/null +++ b/tests/crypto/mbedtls_psa/boards/nrf54l05dk_nrf54l05_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/crypto/mbedtls_psa/boards/nrf54l15dk_nrf54l10_cpuapp.conf b/tests/crypto/mbedtls_psa/boards/nrf54l15dk_nrf54l10_cpuapp.conf new file mode 100644 index 000000000000..70c601183ddf --- /dev/null +++ b/tests/crypto/mbedtls_psa/boards/nrf54l15dk_nrf54l10_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/crypto/mbedtls_psa/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/tests/crypto/mbedtls_psa/boards/nrf54l15dk_nrf54l15_cpuapp.conf new file mode 100644 index 000000000000..70c601183ddf --- /dev/null +++ b/tests/crypto/mbedtls_psa/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/crypto/mbedtls_psa/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/tests/crypto/mbedtls_psa/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 000000000000..70c601183ddf --- /dev/null +++ b/tests/crypto/mbedtls_psa/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/crypto/mbedtls_psa/boards/nrf54lv10dk_nrf54lv10a_cpuapp.conf b/tests/crypto/mbedtls_psa/boards/nrf54lv10dk_nrf54lv10a_cpuapp.conf new file mode 100644 index 000000000000..70c601183ddf --- /dev/null +++ b/tests/crypto/mbedtls_psa/boards/nrf54lv10dk_nrf54lv10a_cpuapp.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/crypto/secp256r1/mbedtls.conf b/tests/crypto/secp256r1/mbedtls.conf index bbc2eb0e6563..c4ea620de55f 100644 --- a/tests/crypto/secp256r1/mbedtls.conf +++ b/tests/crypto/secp256r1/mbedtls.conf @@ -1,6 +1,7 @@ CONFIG_MBEDTLS=y CONFIG_MBEDTLS_PSA_CRYPTO_C=y CONFIG_MBEDTLS_PSA_P256M_DRIVER_ENABLED=y +CONFIG_MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE=65 CONFIG_MBEDTLS_PSA_STATIC_KEY_SLOTS=y CONFIG_MBEDTLS_PSA_KEY_SLOT_COUNT=2 diff --git a/tests/drivers/adc/adc_accuracy_test/testcase.yaml b/tests/drivers/adc/adc_accuracy_test/testcase.yaml index 03f122f9cdaa..1f2f7c0fcfeb 100644 --- a/tests/drivers/adc/adc_accuracy_test/testcase.yaml +++ b/tests/drivers/adc/adc_accuracy_test/testcase.yaml @@ -22,6 +22,7 @@ tests: - frdm_mcxc444 - nrf52840dk/nrf52840 - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/adc/adc_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/adc/adc_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..43c28f0658e5 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/adc/adc_api/testcase.yaml b/tests/drivers/adc/adc_api/testcase.yaml index cd90f5356a51..7b40b93431b9 100644 --- a/tests/drivers/adc/adc_api/testcase.yaml +++ b/tests/drivers/adc/adc_api/testcase.yaml @@ -11,8 +11,8 @@ tests: - nucleo_u031r8 - panb611evb/nrf54l15/cpuapp - panb611evb/nrf54l15/cpuapp/ns - - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54l15dk/nrf54l10/cpuapp/ns + - nrf54lm20dk/nrf54lm20a/cpuapp/ns - bl54l15_dvk/nrf54l10/cpuapp/ns - bl54l15_dvk/nrf54l15/cpuapp/ns - bl54l15u_dvk/nrf54l15/cpuapp/ns diff --git a/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 000000000000..bb3597397b96 --- /dev/null +++ b/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +/ { + aliases { + adc = &adc; + }; +}; diff --git a/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 18e74f72ee26..efc3d8f64b45 100644 --- a/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -1,11 +1,7 @@ /* * SPDX-License-Identifier: Apache-2.0 * - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA */ -/ { - aliases { - adc = &adc; - }; -}; +#include "nrf54h20dk_nrf54h20_common.dtsi" diff --git a/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..bcd359c3aa23 --- /dev/null +++ b/tests/drivers/adc/adc_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" + +&adc { + status = "okay"; +}; diff --git a/tests/drivers/adc/adc_error_cases/testcase.yaml b/tests/drivers/adc/adc_error_cases/testcase.yaml index 57513c78e156..739efb735632 100644 --- a/tests/drivers/adc/adc_error_cases/testcase.yaml +++ b/tests/drivers/adc/adc_error_cases/testcase.yaml @@ -11,6 +11,7 @@ tests: - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - ophelia4ev/nrf54l15/cpuapp - xg24_rb4187c - xg27_dk2602a diff --git a/tests/drivers/build_all/comparator/nrf_comp/diff.overlay b/tests/drivers/build_all/comparator/nrf_comp/diff.overlay index 8b8e9a02c2b1..56b4249d3c53 100644 --- a/tests/drivers/build_all/comparator/nrf_comp/diff.overlay +++ b/tests/drivers/build_all/comparator/nrf_comp/diff.overlay @@ -4,10 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { main-mode = "DIFF"; - psel = "AIN0"; - extrefsel = "AIN1"; + psel = ; + extrefsel = ; sp-mode = "HIGH"; isource = "DISABLED"; status = "okay"; diff --git a/tests/drivers/build_all/comparator/nrf_comp/se.overlay b/tests/drivers/build_all/comparator/nrf_comp/se.overlay index e4eb56f61a92..67798ab4bcf1 100644 --- a/tests/drivers/build_all/comparator/nrf_comp/se.overlay +++ b/tests/drivers/build_all/comparator/nrf_comp/se.overlay @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { main-mode = "SE"; - psel = "AIN0"; + psel = ; refsel = "INT_1V2"; sp-mode = "HIGH"; th-up = <36>; diff --git a/tests/drivers/build_all/comparator/nrf_comp/se_aref.overlay b/tests/drivers/build_all/comparator/nrf_comp/se_aref.overlay index 0d36a3e40b40..04216a7ac10e 100644 --- a/tests/drivers/build_all/comparator/nrf_comp/se_aref.overlay +++ b/tests/drivers/build_all/comparator/nrf_comp/se_aref.overlay @@ -4,10 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { main-mode = "SE"; - psel = "AIN0"; - extrefsel = "AIN1"; + psel = ; + extrefsel = ; refsel = "AREF"; sp-mode = "HIGH"; th-up = <36>; diff --git a/tests/drivers/build_all/comparator/nrf_lpcomp/ext_ref.overlay b/tests/drivers/build_all/comparator/nrf_lpcomp/ext_ref.overlay index 95e44fbed3d6..0d990b2c3f88 100644 --- a/tests/drivers/build_all/comparator/nrf_lpcomp/ext_ref.overlay +++ b/tests/drivers/build_all/comparator/nrf_lpcomp/ext_ref.overlay @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { compatible = "nordic,nrf-lpcomp"; - psel = "AIN0"; + psel = ; refsel = "VDD_4_8"; status = "okay"; }; diff --git a/tests/drivers/build_all/comparator/nrf_lpcomp/int_ref.overlay b/tests/drivers/build_all/comparator/nrf_lpcomp/int_ref.overlay index 7aadd8b3faee..a42ad2f13a16 100644 --- a/tests/drivers/build_all/comparator/nrf_lpcomp/int_ref.overlay +++ b/tests/drivers/build_all/comparator/nrf_lpcomp/int_ref.overlay @@ -4,10 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { compatible = "nordic,nrf-lpcomp"; - psel = "AIN0"; + psel = ; refsel = "AREF"; - extrefsel = "AIN1"; + extrefsel = ; status = "okay"; }; diff --git a/tests/drivers/build_all/comparator/nxp_cmp/frdm_mcxc242.dts b/tests/drivers/build_all/comparator/nxp_cmp/frdm_mcxc242.dts new file mode 100644 index 000000000000..93dc828c7a03 --- /dev/null +++ b/tests/drivers/build_all/comparator/nxp_cmp/frdm_mcxc242.dts @@ -0,0 +1,18 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&cmp { + positive-mux-input = "IN0"; /* PTC6 */ + negative-mux-input = "IN7"; /* DAC */ + dac-vref-source = "VIN2"; + dac-value = <31>; + filter-count = <0x3>; + filter-period = <0xF>; + hysteresis-mode = "LEVEL2"; + enable-high-speed-mode; + invert-output; + enable-pin-out; +}; diff --git a/tests/drivers/build_all/comparator/testcase.yaml b/tests/drivers/build_all/comparator/testcase.yaml index 298dcc884107..1dda00155206 100644 --- a/tests/drivers/build_all/comparator/testcase.yaml +++ b/tests/drivers/build_all/comparator/testcase.yaml @@ -119,3 +119,8 @@ tests: - DTC_OVERLAY_FILE="mcux_acmp/mke15z7_mux_mux.dts" platform_allow: - frdm_ke15z + drivers.build_all.comparator.nxp_cmp.frdm_mcxc242: + extra_args: + - DTC_OVERLAY_FILE="nxp_cmp/frdm_mcxc242.dts" + platform_allow: + - frdm_mcxc242 diff --git a/tests/drivers/build_all/regulator/testcase.yaml b/tests/drivers/build_all/regulator/testcase.yaml index 30d494aca231..b662f0ac2050 100644 --- a/tests/drivers/build_all/regulator/testcase.yaml +++ b/tests/drivers/build_all/regulator/testcase.yaml @@ -3,9 +3,7 @@ tests: drivers.regulator.build: - tags: - - drivers - - regulator + tags: drivers regulator build_only: true platform_allow: - native_sim diff --git a/tests/drivers/clock_control/clock_control_api/testcase.yaml b/tests/drivers/clock_control/clock_control_api/testcase.yaml index d3c2669641fc..3ea6f930f3dc 100644 --- a/tests/drivers/clock_control/clock_control_api/testcase.yaml +++ b/tests/drivers/clock_control/clock_control_api/testcase.yaml @@ -23,6 +23,7 @@ tests: - nrf52840dk/nrf52840 - nrf9160dk/nrf9160 - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: @@ -33,6 +34,7 @@ tests: - nrf52dk/nrf52832 - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: diff --git a/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml b/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml index 708e563900c2..39fec028a40b 100644 --- a/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml +++ b/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml @@ -9,6 +9,7 @@ tests: - nrf52dk/nrf52832 - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: diff --git a/tests/drivers/clock_control/nrf_clock_control/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/clock_control/nrf_clock_control/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..20fe7b305261 --- /dev/null +++ b/tests/drivers/clock_control/nrf_clock_control/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,21 @@ +/* + * Copyright 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&fll16m { + status = "okay"; +}; + +&hsfll120 { + status = "okay"; +}; + +&lfclk { + status = "okay"; +}; + +&canpll { + status = "okay"; +}; diff --git a/tests/drivers/clock_control/nrf_clock_control/src/main.c b/tests/drivers/clock_control/nrf_clock_control/src/main.c index 83fdc98ca193..3612373a867d 100644 --- a/tests/drivers/clock_control/nrf_clock_control/src/main.c +++ b/tests/drivers/clock_control/nrf_clock_control/src/main.c @@ -162,17 +162,10 @@ static const struct test_clk_context lfclk_test_clk_contexts[] = { #define AUXPLL_NODE DT_INST(0, AUXPLL_COMPAT) #define AUXPLL_FREQ DT_PROP(AUXPLL_NODE, nordic_frequency) -/* Gets selected AUXPLL DIV and selects the expected frequency */ -#if AUXPLL_FREQ == NRF_AUXPLL_FREQUENCY_DIV_MIN -#define AUXPLL_FREQ_OUT 80000000 -#elif AUXPLL_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1 -#define AUXPLL_FREQ_OUT 11289591 -#elif AUXPLL_FREQ == NRF_AUXPLL_FREQ_DIV_USB_24M -#define AUXPLL_FREQ_OUT 24000000 -#elif AUXPLL_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_48K -#define AUXPLL_FREQ_OUT 12287963 -#else -/*No use case for NRF_AUXPLL_FREQ_DIV_MAX or others yet*/ + +/* Gets expected AUXPLL frequency */ +#define AUXPLL_FREQ_OUT CLOCK_CONTROL_NRF_AUXPLL_GET_FREQ(AUXPLL_NODE) +#if AUXPLL_FREQ_OUT == 0 #error "Unsupported AUXPLL frequency selection" #endif diff --git a/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml b/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml index 17a783a48084..d789b0e52882 100644 --- a/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml +++ b/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml @@ -15,6 +15,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp extra_configs: @@ -32,6 +33,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp extra_configs: @@ -49,6 +51,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: @@ -65,6 +68,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: @@ -81,6 +85,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: @@ -97,6 +102,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: @@ -113,6 +119,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: @@ -129,6 +136,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: @@ -145,6 +153,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: diff --git a/tests/drivers/clock_control/onoff/testcase.yaml b/tests/drivers/clock_control/onoff/testcase.yaml index 1f557c918ab8..4c50ba3c3ade 100644 --- a/tests/drivers/clock_control/onoff/testcase.yaml +++ b/tests/drivers/clock_control/onoff/testcase.yaml @@ -8,6 +8,7 @@ tests: - nrf52dk/nrf52832 - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - nrf9160dk/nrf9160 - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/comparator/gpio_loopback/boards/frdm_mcxc242.overlay b/tests/drivers/comparator/gpio_loopback/boards/frdm_mcxc242.overlay new file mode 100644 index 000000000000..755db58ab40f --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/frdm_mcxc242.overlay @@ -0,0 +1,25 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + aliases { + test-comp = &cmp; + }; + + zephyr,user { + /* PTC4 output connect to PTC6. */ + test-gpios = <&gpioc 4 GPIO_ACTIVE_HIGH>; + }; +}; + +&cmp { + positive-mux-input = "IN0"; /* PTC6, FRDM-MCXC242 J2-8 */ + negative-mux-input = "IN7"; /* DAC output => 1.65V */ + dac-vref-source = "VIN2"; + dac-value = <31>; +}; diff --git a/tests/drivers/comparator/gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/comparator/gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay deleted file mode 100644 index ddcf8d26cadd..000000000000 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor - * Copyright (c) 2025 Ezurio LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&comp { - main-mode = "SE"; - psel = "AIN4"; /* P1.11 */ - refsel = "INT_1V2"; - sp-mode = "HIGH"; - th-up = <63>; - th-down = <59>; - isource = "DISABLED"; - status = "okay"; -}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay deleted file mode 100644 index f90c2051255f..000000000000 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&comp { - main-mode = "SE"; - psel = "AIN2"; /* P1.02 */ - refsel = "INT_1V2"; - sp-mode = "HIGH"; - th-up = <63>; - th-down = <59>; - isource = "DISABLED"; - status = "okay"; -}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml deleted file mode 100644 index 9d876bfded03..000000000000 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2024 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -name: gpio_loopback_nrf_comp - -boards: - nrf5340dk/nrf5340/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf5340dk_nrf5340_cpuapp.overlay - nrf54h20dk/nrf54h20/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20dk_nrf54h20_cpuapp.overlay - nrf54l15dk/nrf54l15/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay - nrf54lm20dk/nrf54lm20a/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay - ophelia4ev/nrf54l15/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay deleted file mode 100644 index 349cd7051f99..000000000000 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&comp { - compatible = "nordic,nrf-lpcomp"; - psel = "AIN2"; /* P1.02 */ - refsel = "VDD_4_8"; - status = "okay"; -}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay deleted file mode 100644 index ebb652bdd871..000000000000 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&comp { - compatible = "nordic,nrf-lpcomp"; - psel = "AIN4"; /* P1.11 */ - refsel = "VDD_4_8"; - status = "okay"; -}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml deleted file mode 100644 index c2a2005af4d3..000000000000 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2024 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -name: gpio_loopback_nrf_lpcomp - -boards: - nrf5340dk/nrf5340/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf5340dk_nrf5340_cpuapp.overlay - nrf54h20dk/nrf54h20/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20dk_nrf54h20_cpuapp.overlay - nrf54l15dk/nrf54l15/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay - nrf54lm20dk/nrf54lm20a/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay - ophelia4ev/nrf54l15/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf5340_cpuapp_nrf_comp.overlay similarity index 72% rename from tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf5340dk_nrf5340_cpuapp.overlay rename to tests/drivers/comparator/gpio_loopback/socs/nrf5340_cpuapp_nrf_comp.overlay index e11bdcd3173d..68fea53e2b45 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf5340_cpuapp_nrf_comp.overlay @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { main-mode = "SE"; - psel = "AIN0"; /* P0.04 */ + psel = ; /* P0.04 */ refsel = "VDD"; sp-mode = "HIGH"; th-up = <34>; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf5340_cpuapp_nrf_lpcomp.overlay similarity index 66% rename from tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay rename to tests/drivers/comparator/gpio_loopback/socs/nrf5340_cpuapp_nrf_lpcomp.overlay index 58e055a02406..0c571fa21b8f 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf5340_cpuapp_nrf_lpcomp.overlay @@ -1,13 +1,14 @@ /* * Copyright (c) 2024 Nordic Semiconductor - * Copyright (c) 2025 Ezurio LLC * * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { compatible = "nordic,nrf-lpcomp"; - psel = "AIN4"; /* P1.11 */ + psel = ; /* P0.04 */ refsel = "VDD_4_8"; status = "okay"; }; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf54h20_cpuapp_nrf_comp.overlay similarity index 72% rename from tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay rename to tests/drivers/comparator/gpio_loopback/socs/nrf54h20_cpuapp_nrf_comp.overlay index 3a7a8f0ef811..5923e3ab07c8 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf54h20_cpuapp_nrf_comp.overlay @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { main-mode = "SE"; - psel = "AIN4"; /* P1.11 */ + psel = ; /* P1.02 */ refsel = "INT_1V2"; sp-mode = "HIGH"; th-up = <63>; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf54h20_cpuapp_nrf_lpcomp.overlay similarity index 66% rename from tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay rename to tests/drivers/comparator/gpio_loopback/socs/nrf54h20_cpuapp_nrf_lpcomp.overlay index 58e055a02406..66306268a117 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf54h20_cpuapp_nrf_lpcomp.overlay @@ -1,13 +1,14 @@ /* * Copyright (c) 2024 Nordic Semiconductor - * Copyright (c) 2025 Ezurio LLC * * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { compatible = "nordic,nrf-lpcomp"; - psel = "AIN4"; /* P1.11 */ + psel = ; /* P1.02 */ refsel = "VDD_4_8"; status = "okay"; }; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_nrf_comp.overlay similarity index 72% rename from tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay rename to tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_nrf_comp.overlay index ddcf8d26cadd..925417d48ab5 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_nrf_comp.overlay @@ -1,13 +1,14 @@ /* * Copyright (c) 2024 Nordic Semiconductor - * Copyright (c) 2025 Ezurio LLC * * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { main-mode = "SE"; - psel = "AIN4"; /* P1.11 */ + psel = ; /* P1.11 */ refsel = "INT_1V2"; sp-mode = "HIGH"; th-up = <63>; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_nrf_lpcomp.overlay similarity index 66% rename from tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf5340dk_nrf5340_cpuapp.overlay rename to tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_nrf_lpcomp.overlay index d35a20dfc223..e82d8b98521c 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_nrf_lpcomp.overlay @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { compatible = "nordic,nrf-lpcomp"; - psel = "AIN0"; /* P0.04 */ + psel = ; /* P1.11 */ refsel = "VDD_4_8"; status = "okay"; }; diff --git a/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_ns_nrf_comp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_ns_nrf_comp.overlay new file mode 100644 index 000000000000..c79dc80c8423 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_ns_nrf_comp.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15_cpuapp_nrf_comp.overlay" diff --git a/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_ns_nrf_lpcomp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_ns_nrf_lpcomp.overlay new file mode 100644 index 000000000000..2b1e4b9009ca --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf54l15_cpuapp_ns_nrf_lpcomp.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15_cpuapp_nrf_lpcomp.overlay" diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf54lm20a_cpuapp_nrf_comp.overlay similarity index 72% rename from tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay rename to tests/drivers/comparator/gpio_loopback/socs/nrf54lm20a_cpuapp_nrf_comp.overlay index 2709df531950..623bfd9c45f3 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf54lm20a_cpuapp_nrf_comp.overlay @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { main-mode = "SE"; - psel = "AIN1"; /* P1.31 */ + psel = ; /* P1.31 */ refsel = "INT_1V2"; sp-mode = "HIGH"; th-up = <63>; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/socs/nrf54lm20a_cpuapp_nrf_lpcomp.overlay similarity index 66% rename from tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay rename to tests/drivers/comparator/gpio_loopback/socs/nrf54lm20a_cpuapp_nrf_lpcomp.overlay index 0f51a9951a16..db097a9fd6fd 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay +++ b/tests/drivers/comparator/gpio_loopback/socs/nrf54lm20a_cpuapp_nrf_lpcomp.overlay @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &comp { compatible = "nordic,nrf-lpcomp"; - psel = "AIN1"; /* P1.31 */ + psel = ; /* P1.31 */ refsel = "VDD_4_8"; status = "okay"; }; diff --git a/tests/drivers/comparator/gpio_loopback/testcase.yaml b/tests/drivers/comparator/gpio_loopback/testcase.yaml index dfebf3644756..706e2ac3757f 100644 --- a/tests/drivers/comparator/gpio_loopback/testcase.yaml +++ b/tests/drivers/comparator/gpio_loopback/testcase.yaml @@ -19,21 +19,21 @@ tests: - frdm_ke15z drivers.comparator.gpio_loopback.nrf_comp: extra_args: - - SNIPPET_ROOT="." - - SNIPPET="gpio_loopback_nrf_comp" + - FILE_SUFFIX="nrf_comp" platform_allow: - nrf5340dk/nrf5340/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.comparator.gpio_loopback.nrf_lpcomp: extra_args: - - SNIPPET_ROOT="." - - SNIPPET="gpio_loopback_nrf_lpcomp" + - FILE_SUFFIX="nrf_lpcomp" platform_allow: - nrf5340dk/nrf5340/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/counter/counter_basic_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..b34c0dadce5c --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_common.dtsi" diff --git a/tests/drivers/flash/common/boards/mx25uw63_low_freq.overlay b/tests/drivers/flash/common/boards/mx25uw63_low_freq.overlay new file mode 100644 index 000000000000..8dacdb15ff55 --- /dev/null +++ b/tests/drivers/flash/common/boards/mx25uw63_low_freq.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mx25uw63 { + status = "okay"; + mspi-max-frequency = ; + transfer-timeout = <500>; +}; diff --git a/tests/drivers/flash/common/boards/mx25uw63_single_io.overlay b/tests/drivers/flash/common/boards/mx25uw63_single_io.overlay index 062020aea353..e74369f372b1 100644 --- a/tests/drivers/flash/common/boards/mx25uw63_single_io.overlay +++ b/tests/drivers/flash/common/boards/mx25uw63_single_io.overlay @@ -58,4 +58,5 @@ status = "okay"; mspi-max-frequency = ; mspi-io-mode = "MSPI_IO_MODE_SINGLE"; + transfer-timeout = <1000>; }; diff --git a/tests/drivers/flash/common/boards/mx25uw63_single_io_4B_addr_sreset.overlay b/tests/drivers/flash/common/boards/mx25uw63_single_io_4B_addr_sreset.overlay new file mode 100644 index 000000000000..f2f74b269676 --- /dev/null +++ b/tests/drivers/flash/common/boards/mx25uw63_single_io_4B_addr_sreset.overlay @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + + /delete-node/ exmif_default; + /delete-node/ exmif_sleep; + + exmif_default: exmif_default { + group1 { + psels = , + , + , + , + , + , + , + , + , + ; + nordic,drive-mode = ; + }; + }; + + exmif_sleep: exmif_sleep { + group1 { + low-power-enable; + psels = , + , + , + , + , + , + , + , + , + ; + }; + }; +}; + +&gpio6 { + status = "okay"; +}; + +&exmif { + status = "okay"; + pinctrl-0 = <&exmif_default>; + pinctrl-1 = <&exmif_sleep>; + pinctrl-names = "default", "sleep"; + ce-gpios = <&gpio6 3 GPIO_ACTIVE_LOW>; +}; + +&mx25uw63 { + status = "okay"; + mspi-max-frequency = ; + mspi-io-mode = "MSPI_IO_MODE_SINGLE"; + use-4byte-addressing; + initial-soft-reset; + transfer-timeout = <1000>; +}; diff --git a/tests/drivers/flash/common/boards/nrf52840dk_qer_none.overlay b/tests/drivers/flash/common/boards/nrf52840dk_qer_none.overlay new file mode 100644 index 000000000000..190537bf8536 --- /dev/null +++ b/tests/drivers/flash/common/boards/nrf52840dk_qer_none.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2025, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mx25r64 { + quad-enable-requirements = "NONE"; +}; diff --git a/tests/drivers/flash/common/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/flash/common/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 22c24c32f6d8..5272bb8fdde3 100644 --- a/tests/drivers/flash/common/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/flash/common/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -4,6 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ +/ { + zephyr,user { + test-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpio0 { + status = "okay"; +}; + &gpio6 { status = "okay"; zephyr,pm-device-runtime-auto; @@ -16,4 +26,5 @@ &mx25uw63 { status = "okay"; + supply-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; }; diff --git a/tests/drivers/flash/common/boards/nrf54l15dk_remove_dt_sfdp.overlay b/tests/drivers/flash/common/boards/nrf54l15dk_remove_dt_sfdp.overlay new file mode 100644 index 000000000000..b6ffcf23c785 --- /dev/null +++ b/tests/drivers/flash/common/boards/nrf54l15dk_remove_dt_sfdp.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mx25r64 { +/delete-property/ jedec-id; +/delete-property/ sfdp-bfp; +/delete-property/ has-dpd; +/delete-property/ t-enter-dpd; +/delete-property/ t-exit-dpd; +}; diff --git a/tests/drivers/flash/common/src/main.c b/tests/drivers/flash/common/src/main.c index 337876a9e8d7..df484f825e89 100644 --- a/tests/drivers/flash/common/src/main.c +++ b/tests/drivers/flash/common/src/main.c @@ -9,6 +9,7 @@ #include #include #include +#include #if defined(CONFIG_NORDIC_QSPI_NOR) #define TEST_AREA_DEV_NODE DT_INST(0, nordic_qspi_nor) @@ -64,6 +65,11 @@ #error There is no flash device enabled or it is missing Kconfig options #endif +#if DT_NODE_HAS_PROP(DT_BUS(TEST_AREA_DEV_NODE), packet_data_limit) +#define CONTROLLER_PACKET_DATA_LIMIT DT_PROP(DT_BUS(TEST_AREA_DEV_NODE), packet_data_limit) +#define BUFFER_SIZE_OVER_PACKET_LIMIT CONTROLLER_PACKET_DATA_LIMIT + 1 +#endif + static const struct device *const flash_dev = TEST_AREA_DEVICE; static struct flash_pages_info page_info; static uint8_t __aligned(4) expected[EXPECTED_SIZE]; @@ -327,6 +333,55 @@ ZTEST(flash_driver, test_flash_erase) zassert_not_equal(expected[0], erase_value, "These values shall be different"); } +ZTEST(flash_driver, test_flash_write_read_over_the_packet_limit) +{ + +#if !defined(CONTROLLER_PACKET_DATA_LIMIT) + TC_PRINT("Given bus controller does not have 'packet_data_limit' property\n"); + ztest_test_skip(); +#else + int rc; + const uint8_t pattern = 0xA1; + static uint8_t large_data_buf[BUFFER_SIZE_OVER_PACKET_LIMIT]; + + /* Flatten area corresponding to the size of two packets */ + rc = flash_flatten(flash_dev, page_info.start_offset, 2 * CONTROLLER_PACKET_DATA_LIMIT); + zassert_equal(rc, 0, "Flash flatten failed: %d", rc); + + /* Fill flash area with buffer size over the configured packet limit */ + rc = flash_fill(flash_dev, pattern, page_info.start_offset, BUFFER_SIZE_OVER_PACKET_LIMIT); + zassert_equal(rc, 0, "Flash fill failed"); + + /* Read flash area with buffer size over the MSPI packet limit */ + rc = flash_read(flash_dev, page_info.start_offset, large_data_buf, + BUFFER_SIZE_OVER_PACKET_LIMIT); + zassert_equal(rc, 0, "Flash read failed"); + + /* Compare read data to the pre-defined pattern */ + for (int i = 0; i < BUFFER_SIZE_OVER_PACKET_LIMIT; i++) { + zassert_equal(large_data_buf[i], pattern, + "large_data_buf[%u]=%x read, does not match written pattern %x", i, + large_data_buf[i], pattern); + } +#endif +} + +ZTEST(flash_driver, test_supply_gpios_control) +{ + if (!DT_NODE_HAS_PROP(TEST_AREA_DEV_NODE, supply_gpios)) { + ztest_test_skip(); + } + +#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), test_gpios) + const struct gpio_dt_spec test_gpio = + GPIO_DT_SPEC_GET(DT_PATH(zephyr_user), test_gpios); + zassert_true(gpio_is_ready_dt(&test_gpio), "Test GPIO is not ready\n"); + zassert_ok(gpio_pin_configure_dt(&test_gpio, GPIO_INPUT | GPIO_PULL_DOWN), + "Failed to configure test pin\n"); + zassert_equal(gpio_pin_get(test_gpio.port, test_gpio.pin), 1, "Supply GPIO is not set\n"); +#endif +} + struct test_cb_data_type { uint32_t page_counter; /* used to count how many pages was iterated */ uint32_t exit_page; /* terminate iteration when this page is reached */ diff --git a/tests/drivers/flash/common/testcase.yaml b/tests/drivers/flash/common/testcase.yaml index 34123ffde77f..d4ac7537b54d 100644 --- a/tests/drivers/flash/common/testcase.yaml +++ b/tests/drivers/flash/common/testcase.yaml @@ -29,6 +29,13 @@ tests: - CONFIG_TEST_DRIVER_FLASH_SIZE=8388608 integration_platforms: - nrf52840dk/nrf52840 + drivers.flash.common.nrf_qspi_nor.qer_none: + build_only: true + platform_allow: nrf52840dk/nrf52840 + extra_args: + - DTC_OVERLAY_FILE=boards/nrf52840dk_qer_none.overlay + integration_platforms: + - nrf52840dk/nrf52840 drivers.flash.common.nrf_qspi_nor_4B_addr: platform_allow: nrf52840dk/nrf52840 extra_configs: @@ -59,8 +66,24 @@ tests: - nrf54l15dk/nrf54l05/cpuapp - nrf54l15dk/nrf54l10/cpuapp - nrf54l15dk/nrf54l15/cpuapp + harness_config: + fixture: external_flash + drivers.flash.common.no_explicit_erase.sfdp_runtime: + platform_allow: + - nrf54l15dk/nrf54l05/cpuapp + - nrf54l15dk/nrf54l10/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + harness_config: + fixture: external_flash + extra_configs: + - CONFIG_SPI_NOR_SFDP_RUNTIME=y + extra_args: + - DTC_OVERLAY_FILE=boards/nrf54l15dk_remove_dt_sfdp.overlay + drivers.flash.common.no_explicit_erase.nrf54h: + platform_allow: - nrf54h20dk/nrf54h20/cpuapp - - ophelia4ev/nrf54l15/cpuapp + harness_config: + fixture: gpio_loopback drivers.flash.common.nrf54lm20a: platform_allow: - nrf54lm20dk/nrf54lm20a/cpuapp @@ -172,6 +195,8 @@ tests: - nrf54h20dk/nrf54h20/cpuapp extra_args: - EXTRA_DTC_OVERLAY_FILE=boards/mx25uw63_single_io.overlay + harness_config: + fixture: gpio_loopback drivers.flash.common.ra_qspi_nor: filter: CONFIG_FLASH_RENESAS_RA_QSPI and dt_compat_enabled("renesas,ra-qspi-nor") platform_allow: @@ -182,3 +207,17 @@ tests: extra_args: - DTC_OVERLAY_FILE="./boards/${BOARD}_qspi_nor.overlay" - CONF_FILE="./prj.conf ./boards/${BOARD}_qspi_nor.conf" + drivers.flash.common.mspi_single_io.4B_addr_soft_reset: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE=boards/mx25uw63_single_io_4B_addr_sreset.overlay + harness_config: + fixture: gpio_loopback + drivers.flash.common.mspi_low_frequency: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE=boards/mx25uw63_low_freq.overlay + harness_config: + fixture: gpio_loopback diff --git a/tests/drivers/flash/negative_tests/sysbuild.conf b/tests/drivers/flash/negative_tests/sysbuild.conf new file mode 100644 index 000000000000..6408669a8474 --- /dev/null +++ b/tests/drivers/flash/negative_tests/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/gpio/gpio_basic_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/gpio/gpio_basic_api/testcase.yaml b/tests/drivers/gpio/gpio_basic_api/testcase.yaml index 2acaf8d8f621..86431a3dbe5e 100644 --- a/tests/drivers/gpio/gpio_basic_api/testcase.yaml +++ b/tests/drivers/gpio/gpio_basic_api/testcase.yaml @@ -27,6 +27,7 @@ tests: drivers.gpio.nrf_sense_edge.nrf54l: platform_allow: - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns extra_args: "EXTRA_DTC_OVERLAY_FILE=boards/nrf54l_sense_edge.overlay" drivers.gpio.mr_canhubk3_wkpu: diff --git a/tests/drivers/gpio/gpio_get_direction/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/drivers/gpio/gpio_get_direction/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..cbc7b679be00 --- /dev/null +++ b/tests/drivers/gpio/gpio_get_direction/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/ { + aliases { + led0 = &led0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio9 0 GPIO_ACTIVE_HIGH>; + label = "Green LED 0"; + }; + }; +}; + +&gpiote130 { + status = "okay"; +}; + +&gpio9 { + status = "okay"; +}; diff --git a/tests/drivers/gpio/gpio_hogs/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/drivers/gpio/gpio_hogs/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..3d0a4ccf5a6d --- /dev/null +++ b/tests/drivers/gpio/gpio_hogs/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/ { + zephyr,user { + output-high-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + output-low-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; + input-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; + }; +}; + +&gpio0 { + status = "okay"; + hog1 { + gpio-hog; + gpios = <3 GPIO_ACTIVE_LOW>; + output-high; + }; + + hog2 { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + output-low; + }; + + hog3 { + gpio-hog; + gpios = <1 GPIO_ACTIVE_LOW>; + input; + }; +}; + +&gpiote130 { + status = "okay"; +}; diff --git a/tests/drivers/gpio/gpio_hogs/testcase.yaml b/tests/drivers/gpio/gpio_hogs/testcase.yaml index 3de068163b85..43b01894f5fb 100644 --- a/tests/drivers/gpio/gpio_hogs/testcase.yaml +++ b/tests/drivers/gpio/gpio_hogs/testcase.yaml @@ -11,6 +11,7 @@ tests: - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - nucleo_g474re - nrf52_bsim - nrf5340bsim/nrf5340/cpuapp diff --git a/tests/drivers/gpio/gpio_nrf/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/drivers/gpio/gpio_nrf/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..cbc7b679be00 --- /dev/null +++ b/tests/drivers/gpio/gpio_nrf/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/ { + aliases { + led0 = &led0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio9 0 GPIO_ACTIVE_HIGH>; + label = "Green LED 0"; + }; + }; +}; + +&gpiote130 { + status = "okay"; +}; + +&gpio9 { + status = "okay"; +}; diff --git a/tests/drivers/i2c/i2c_nrfx_twim/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/drivers/i2c/i2c_nrfx_twim/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..1d4259cacc11 --- /dev/null +++ b/tests/drivers/i2c/i2c_nrfx_twim/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * SDA = P2.8 and P2.9 + * SCL = P1.2 and P1.3 + */ + +/ { + aliases { + i2c-controller = &i2c130; + i2c-controller-target = &i2c131; + }; +}; + +&pinctrl { + i2c130_default: i2c130_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c130_sleep: i2c130_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c131_default: i2c131_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c131_sleep: i2c131_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c130 { + compatible = "nordic,nrf-twim"; + clock-frequency = ; + pinctrl-0 = <&i2c130_default>; + pinctrl-1 = <&i2c130_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + status = "okay"; +}; + +&i2c131 { + compatible = "nordic,nrf-twis"; + clock-frequency = ; + pinctrl-0 = <&i2c131_default>; + pinctrl-1 = <&i2c131_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; +}; diff --git a/tests/drivers/i2c/i2c_nrfx_twim/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/i2c/i2c_nrfx_twim/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 000000000000..1fc56cc63298 --- /dev/null +++ b/tests/drivers/i2c/i2c_nrfx_twim/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * SDA = P1.13 and P1.14 + * SCL = P1.23 and P1.24 + */ + +/ { + aliases { + i2c-controller = &i2c21; + i2c-controller-target = &i2c22; + }; +}; + +&pinctrl { + i2c21_default: i2c21_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c21_sleep: i2c21_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c22_default: i2c22_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c22_sleep: i2c22_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c21 { + pinctrl-0 = <&i2c21_default>; + pinctrl-1 = <&i2c21_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + status = "okay"; +}; + +&i2c22 { + compatible = "nordic,nrf-twis"; + pinctrl-0 = <&i2c22_default>; + pinctrl-1 = <&i2c22_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; +}; diff --git a/tests/drivers/i2c/i2c_nrfx_twim/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/i2c/i2c_nrfx_twim/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..69aedabd69dc --- /dev/null +++ b/tests/drivers/i2c/i2c_nrfx_twim/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c130 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; + +&i2c131 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; diff --git a/tests/drivers/i2c/i2c_nrfx_twim/sysbuild/vpr_launcher/prj.conf b/tests/drivers/i2c/i2c_nrfx_twim/sysbuild/vpr_launcher/prj.conf new file mode 100644 index 000000000000..d6c8f934808e --- /dev/null +++ b/tests/drivers/i2c/i2c_nrfx_twim/sysbuild/vpr_launcher/prj.conf @@ -0,0 +1,3 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# nothing here diff --git a/tests/drivers/i2c/i2c_nrfx_twim/testcase.yaml b/tests/drivers/i2c/i2c_nrfx_twim/testcase.yaml index e35dd49dbb76..42d1d98f3af8 100644 --- a/tests/drivers/i2c/i2c_nrfx_twim/testcase.yaml +++ b/tests/drivers/i2c/i2c_nrfx_twim/testcase.yaml @@ -12,7 +12,9 @@ tests: platform_allow: - nrf5340dk/nrf5340/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf5340dk/nrf5340/cpuapp - nrf54l15dk/nrf54l15/cpuapp diff --git a/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuppr.conf b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuppr.conf new file mode 100644 index 000000000000..baa00bdf40f7 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuppr.conf @@ -0,0 +1,5 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256 +CONFIG_GPIO=y diff --git a/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..0138f287de8e --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * SDA = P2.8 and P2.9 + * SCL = P1.2 and P1.3 + */ + +/ { + zephyr,user { + sda0-gpios = <&gpio2 8 0>; + scl0-gpios = <&gpio1 2 0>; + sda1-gpios = <&gpio2 9 0>; + scl1-gpios = <&gpio1 3 0>; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&pinctrl { + i2c130_default: i2c130_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c130_sleep: i2c130_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c131_default: i2c131_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c131_sleep: i2c131_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c130 { + clock-frequency = ; + pinctrl-0 = <&i2c130_default>; + pinctrl-1 = <&i2c130_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + status = "okay"; + + eeprom1: eeprom@56 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x56>; + address-width = <8>; + size = <256>; + }; +}; + +&i2c131 { + compatible = "nordic,nrf-twis"; + clock-frequency = ; + pinctrl-0 = <&i2c131_default>; + pinctrl-1 = <&i2c131_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; + + eeprom0: eeprom@54 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x54>; + address-width = <8>; + size = <256>; + }; +}; + +&gpiote130 { + status = "okay"; +}; diff --git a/tests/drivers/i2c/i2c_target_api/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/i2c/i2c_target_api/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..69aedabd69dc --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c130 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; + +&i2c131 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; diff --git a/tests/drivers/i2c/i2c_target_api/sysbuild/vpr_launcher/prj.conf b/tests/drivers/i2c/i2c_target_api/sysbuild/vpr_launcher/prj.conf new file mode 100644 index 000000000000..d6c8f934808e --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/sysbuild/vpr_launcher/prj.conf @@ -0,0 +1,3 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# nothing here diff --git a/tests/drivers/i2c/i2c_target_api/testcase.yaml b/tests/drivers/i2c/i2c_target_api/testcase.yaml index 13ef2bb16c4c..35207c6ab91b 100644 --- a/tests/drivers/i2c/i2c_target_api/testcase.yaml +++ b/tests/drivers/i2c/i2c_target_api/testcase.yaml @@ -65,6 +65,7 @@ tests: - max32690evkit/max32690/m4 - nrf5340dk/nrf5340/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/i2s/i2s_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/i2s/i2s_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/drivers/i2s/i2s_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/i2s/i2s_api/src/test_i2s_errors.c b/tests/drivers/i2s/i2s_api/src/test_i2s_errors.c index 477292d84c26..230a71e95d4d 100644 --- a/tests/drivers/i2s/i2s_api/src/test_i2s_errors.c +++ b/tests/drivers/i2s/i2s_api/src/test_i2s_errors.c @@ -76,6 +76,9 @@ ZTEST_USER(i2s_errors, test_i2s_config_attempt_in_wrong_state) err = i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_STOP); zassert_equal(err, 0, "I2S_TRIGGER_STOP unexpected error: %d", err); + err = i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_DROP); + zassert_equal(err, 0, "I2S_TRIGGER_DROP unexpected error: %d", err); + zassert_not_equal( config_err, 0, "I2S configuration should not be possible in states other than I2S_STATE_READY"); diff --git a/tests/drivers/i2s/i2s_speed/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/i2s/i2s_speed/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/drivers/i2s/i2s_speed/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/mbox/mbox_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/mbox/mbox_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 000000000000..334ba0fa5b42 --- /dev/null +++ b/tests/drivers/mbox/mbox_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,23 @@ +/* + * Copyright 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + mbox-consumer { + compatible = "vnd,mbox-consumer"; + mboxes = <&cpuapp_vevif_tx 21>, <&cpuapp_vevif_tx 32>, + <&cpuapp_vevif_rx 20>, <&cpuapp_vevif_rx 32>; + mbox-names = "remote_valid", "remote_incorrect", + "local_valid", "local_incorrect"; + + }; +}; + +&cpuapp_vevif_rx { + status = "okay"; +}; + +&cpuapp_vevif_tx { + status = "okay"; +}; diff --git a/tests/drivers/mbox/mbox_error_cases/sample.yaml b/tests/drivers/mbox/mbox_error_cases/sample.yaml index 2746a1c29044..a285478b4235 100644 --- a/tests/drivers/mbox/mbox_error_cases/sample.yaml +++ b/tests/drivers/mbox/mbox_error_cases/sample.yaml @@ -17,8 +17,10 @@ tests: tests.drivers.mbox_error_cases.nrf54l: platform_allow: - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp extra_args: SNIPPET=nordic-flpr diff --git a/tests/drivers/mbox/mbox_error_cases/src/main.c b/tests/drivers/mbox/mbox_error_cases/src/main.c index 54a4a628ec23..377ab6b8be43 100644 --- a/tests/drivers/mbox/mbox_error_cases/src/main.c +++ b/tests/drivers/mbox/mbox_error_cases/src/main.c @@ -11,7 +11,8 @@ int dummy_value; #if defined(CONFIG_SOC_NRF54L05) || defined(CONFIG_SOC_NRF54L10) || \ - defined(CONFIG_SOC_NRF54L15) || defined(CONFIG_SOC_NRF54H20) + defined(CONFIG_SOC_NRF54L15) || defined(CONFIG_SOC_NRF54H20) || \ + defined(CONFIG_SOC_NRF54LM20A) #define EXPECTED_MTU_VALUE (0) #define DATA_TRANSFER_MODE_SUPPORTED (0) #define REMOTE_BUSY_SUPPORTED (0) diff --git a/tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..2e6b6cf5eacc --- /dev/null +++ b/tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + mspi0 = &exmif; + }; + + psa_rng: psa-rng { + status = "disabled"; + }; +}; + +&gpio6 { + status = "okay"; +}; + +&exmif { + status = "okay"; +}; + +&mx25uw63 { + status = "okay"; +}; diff --git a/tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 000000000000..a026df97a458 --- /dev/null +++ b/tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +CONFIG_PM=n diff --git a/tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 000000000000..09b4edc100a4 --- /dev/null +++ b/tests/drivers/mspi/flash/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,5 @@ +/ { + psa_rng: psa-rng { + status = "disabled"; + }; +}; diff --git a/tests/drivers/mspi/flash/testcase.yaml b/tests/drivers/mspi/flash/testcase.yaml index 72755fd2aa43..ae1db5d4d6d2 100644 --- a/tests/drivers/mspi/flash/testcase.yaml +++ b/tests/drivers/mspi/flash/testcase.yaml @@ -1,16 +1,18 @@ # Copyright (c) 2024 Ambiq Micro Inc. # SPDX-License-Identifier: Apache-2.0 +common: + tags: + - drivers + - mspi + - flash + harness: ztest + tests: drivers.mspi.flash: - tags: - - drivers - - mspi - - flash filter: dt_compat_enabled("zephyr,mspi-emul-flash") or dt_compat_enabled("jedec,spi-nor") or dt_compat_enabled("jedec,mspi-nor") or dt_compat_enabled("mspi-atxp032") or dt_compat_enabled("mspi-is25xX0xx") - harness: ztest platform_allow: - native_sim - apollo3p_evb @@ -20,15 +22,23 @@ tests: - apollo3p_evb - apollo510_evb drivers.mspi.flash.xip_read: - tags: - - drivers - - mspi - - flash filter: dt_compat_enabled("mspi-is25xX0xx") - harness: ztest platform_allow: - apollo510_evb integration_platforms: - apollo510_evb extra_configs: - CONFIG_FLASH_MSPI_XIP_READ=y + drivers.mspi.flash.mspi_dw_system_workqueue: + filter: dt_alias_exists("mspi0") and dt_compat_enabled("jedec,mspi-nor") + and CONFIG_MSPI_DW + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_configs: + - CONFIG_MSPI_DW_HANDLE_FIFOS_IN_SYSTEM_WORKQUEUE=y + drivers.mspi.flash.mspi_nor_no_multithreading: + filter: dt_alias_exists("mspi0") and CONFIG_FLASH_MSPI_NOR + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_configs: + - CONFIG_MULTITHREADING=n diff --git a/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp_ns.conf b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp_ns.conf new file mode 100644 index 000000000000..795414a504ab --- /dev/null +++ b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp_ns.conf @@ -0,0 +1 @@ +CONFIG_SKIP_EDGE_NUM=4 diff --git a/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/pwm/pwm_gpio_loopback/testcase.yaml b/tests/drivers/pwm/pwm_gpio_loopback/testcase.yaml index 2959739d50be..448eccb5e3bb 100644 --- a/tests/drivers/pwm/pwm_gpio_loopback/testcase.yaml +++ b/tests/drivers/pwm/pwm_gpio_loopback/testcase.yaml @@ -20,6 +20,7 @@ tests: platform_allow: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/sensor/temp_sensor/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/sensor/temp_sensor/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/1m333333hz.overlay b/tests/drivers/spi/spi_controller_peripheral/1m333333hz.overlay similarity index 100% rename from tests/drivers/spi/spi_controller_peripheral/boards/1m333333hz.overlay rename to tests/drivers/spi/spi_controller_peripheral/1m333333hz.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/1mhz.overlay b/tests/drivers/spi/spi_controller_peripheral/1mhz.overlay similarity index 100% rename from tests/drivers/spi/spi_controller_peripheral/boards/1mhz.overlay rename to tests/drivers/spi/spi_controller_peripheral/1mhz.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/250khz.overlay b/tests/drivers/spi/spi_controller_peripheral/250khz.overlay similarity index 100% rename from tests/drivers/spi/spi_controller_peripheral/boards/250khz.overlay rename to tests/drivers/spi/spi_controller_peripheral/250khz.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/2m666666hz.overlay b/tests/drivers/spi/spi_controller_peripheral/2m666666hz.overlay similarity index 100% rename from tests/drivers/spi/spi_controller_peripheral/boards/2m666666hz.overlay rename to tests/drivers/spi/spi_controller_peripheral/2m666666hz.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/2mhz.overlay b/tests/drivers/spi/spi_controller_peripheral/2mhz.overlay similarity index 100% rename from tests/drivers/spi/spi_controller_peripheral/boards/2mhz.overlay rename to tests/drivers/spi/spi_controller_peripheral/2mhz.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/4mhz.overlay b/tests/drivers/spi/spi_controller_peripheral/4mhz.overlay similarity index 100% rename from tests/drivers/spi/spi_controller_peripheral/boards/4mhz.overlay rename to tests/drivers/spi/spi_controller_peripheral/4mhz.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/500khz.overlay b/tests/drivers/spi/spi_controller_peripheral/500khz.overlay similarity index 100% rename from tests/drivers/spi/spi_controller_peripheral/boards/500khz.overlay rename to tests/drivers/spi/spi_controller_peripheral/500khz.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/8mhz.overlay b/tests/drivers/spi/spi_controller_peripheral/8mhz.overlay similarity index 100% rename from tests/drivers/spi/spi_controller_peripheral/boards/8mhz.overlay rename to tests/drivers/spi/spi_controller_peripheral/8mhz.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf52840dk_nrf52840.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf52840dk_nrf52840.overlay index 72bb74931860..db08930ddd9a 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf52840dk_nrf52840.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf52840dk_nrf52840.overlay @@ -50,6 +50,7 @@ overrun-character = <0x00>; cs-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; zephyr,pm-device-runtime-auto; + dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; spi-max-frequency = ; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_common.dtsi index bad32ea4d1c9..6aeb34699d9f 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_common.dtsi +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -60,6 +60,7 @@ overrun-character = <0x00>; cs-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; zephyr,pm-device-runtime-auto; + dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay index 81b1303ede15..ee6a5e3c19eb 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay @@ -60,6 +60,7 @@ memory-regions = <&dma_fast_region>; cs-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; zephyr,pm-device-runtime-auto; + dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast_spis.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast_spis.overlay index be975607c1b5..ba00e866b60e 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast_spis.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast_spis.overlay @@ -110,6 +110,7 @@ memory-regions = <&dma_fast_region>; cs-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; zephyr,pm-device-runtime-auto; + dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index 7915897066d8..cf83ac20a270 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -54,6 +54,7 @@ overrun-character = <0x00>; cs-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; zephyr,pm-device-runtime-auto; + dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay index 7fd8d54d8db5..1c36704b5ba2 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay @@ -54,6 +54,7 @@ overrun-character = <0x00>; cs-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; zephyr,pm-device-runtime-auto; + dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/spi/spi_controller_peripheral/testcase.yaml b/tests/drivers/spi/spi_controller_peripheral/testcase.yaml index a4581e54820d..3fa4cb16db6b 100644 --- a/tests/drivers/spi/spi_controller_peripheral/testcase.yaml +++ b/tests/drivers/spi/spi_controller_peripheral/testcase.yaml @@ -12,6 +12,7 @@ common: - nrf54h20dk/nrf54h20/cpurad - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp @@ -19,35 +20,35 @@ tests: drivers.spi.spi_mode0: extra_configs: - CONFIG_TESTED_SPI_MODE=0 - extra_args: EXTRA_DTC_OVERLAY_FILE="boards/250khz.overlay" + extra_args: EXTRA_DTC_OVERLAY_FILE="250khz.overlay" integration_platforms: - nrf52840dk/nrf52840 drivers.spi.spi_mode1: extra_configs: - CONFIG_TESTED_SPI_MODE=1 - extra_args: EXTRA_DTC_OVERLAY_FILE="boards/500khz.overlay" + extra_args: EXTRA_DTC_OVERLAY_FILE="500khz.overlay" integration_platforms: - nrf52840dk/nrf52840 drivers.spi.spi_mode2: extra_configs: - CONFIG_TESTED_SPI_MODE=2 - extra_args: EXTRA_DTC_OVERLAY_FILE="boards/1mhz.overlay" + extra_args: EXTRA_DTC_OVERLAY_FILE="1mhz.overlay" integration_platforms: - nrf52840dk/nrf52840 drivers.spi.spi_mode3: extra_configs: - CONFIG_TESTED_SPI_MODE=3 - extra_args: EXTRA_DTC_OVERLAY_FILE="boards/2mhz.overlay" + extra_args: EXTRA_DTC_OVERLAY_FILE="2mhz.overlay" integration_platforms: - nrf52840dk/nrf52840 drivers.spi.spi_1M333333Hz: extra_configs: - CONFIG_TESTED_SPI_MODE=0 - extra_args: EXTRA_DTC_OVERLAY_FILE="boards/1m333333hz.overlay" + extra_args: EXTRA_DTC_OVERLAY_FILE="1m333333hz.overlay" integration_platforms: - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp @@ -55,7 +56,7 @@ tests: drivers.spi.spi_2M666666Hz: extra_configs: - CONFIG_TESTED_SPI_MODE=0 - extra_args: EXTRA_DTC_OVERLAY_FILE="boards/2m666666hz.overlay" + extra_args: EXTRA_DTC_OVERLAY_FILE="2m666666hz.overlay" integration_platforms: - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp @@ -63,14 +64,14 @@ tests: drivers.spi.spi_4MHz: extra_configs: - CONFIG_TESTED_SPI_MODE=2 - extra_args: EXTRA_DTC_OVERLAY_FILE="boards/4mhz.overlay" + extra_args: EXTRA_DTC_OVERLAY_FILE="4mhz.overlay" integration_platforms: - nrf52840dk/nrf52840 drivers.spi.spi_8MHz: extra_configs: - CONFIG_TESTED_SPI_MODE=1 - extra_args: EXTRA_DTC_OVERLAY_FILE="boards/8mhz.overlay" + extra_args: EXTRA_DTC_OVERLAY_FILE="8mhz.overlay" integration_platforms: - nrf52840dk/nrf52840 @@ -81,6 +82,7 @@ tests: - nrf54h20dk/nrf54h20/cpurad - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp @@ -94,6 +96,7 @@ tests: - nrf54h20dk/nrf54h20/cpurad - nrf54h20dk/nrf54h20/cpuppr - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp @@ -109,6 +112,8 @@ tests: extra_configs: - CONFIG_TESTED_SPI_MODE=0 - CONFIG_NRF_SYS_EVENT=y + - CONFIG_SOC_NRF_FORCE_CONSTLAT=y + - CONFIG_POWER_DOMAIN=n extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay" platform_exclude: - nrf52840dk/nrf52840 diff --git a/tests/drivers/spi/spi_error_cases/testcase.yaml b/tests/drivers/spi/spi_error_cases/testcase.yaml index 9ad509baddb0..eb3f4c78c580 100644 --- a/tests/drivers/spi/spi_error_cases/testcase.yaml +++ b/tests/drivers/spi/spi_error_cases/testcase.yaml @@ -11,8 +11,10 @@ tests: drivers.spi.spi_error_cases: platform_allow: - nrf52840dk/nrf52840 - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuppr + - nrf54h20dk/nrf54h20/cpurad + - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf index ad922ab8d26f..725924348b53 100644 --- a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -1 +1 @@ -CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=12 +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=15 diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 17c2909717f2..aa5dc30239ce 100644 --- a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -7,15 +7,4 @@ &spi130 { memory-regions = <&cpuapp_dma_region>; - zephyr,pm-device-runtime-auto; - slow@0 { - compatible = "test-spi-loopback-slow"; - reg = <0>; - spi-max-frequency = ; - }; - fast@0 { - compatible = "test-spi-loopback-fast"; - reg = <0>; - spi-max-frequency = ; - }; }; diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.conf b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.conf deleted file mode 100644 index af7d7e938e0f..000000000000 --- a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SPI_LARGE_BUFFER_SIZE=1024 diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf new file mode 100644 index 000000000000..250de8d4487a --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf @@ -0,0 +1,2 @@ +CONFIG_SPI_LARGE_BUFFER_SIZE=1024 +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=15 diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr_xip.overlay similarity index 66% rename from tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.overlay rename to tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr_xip.overlay index cea31612851b..76ebe3410375 100644 --- a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr.overlay +++ b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuppr_xip.overlay @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpurad.conf index ad922ab8d26f..725924348b53 100644 --- a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpurad.conf +++ b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -1 +1 @@ -CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=12 +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=15 diff --git a/tests/drivers/timer/nrf_grtc_timer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 04580b71480b..7ae959267039 100644 --- a/tests/drivers/timer/nrf_grtc_timer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -2,4 +2,21 @@ &grtc { /delete-property/ child-owned-channels; + interrupts = <109 2>; +}; + +test_timer: &timer131 { + status = "okay"; + interrupts = <419 1>; +}; + +&timer130 { + status = "okay"; + prescaler = <0>; +}; + +/ { + chosen { + zephyr,cpu-load-counter = &timer130; + }; }; diff --git a/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 000000000000..7bcede529b0e --- /dev/null +++ b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&grtc { + interrupts = <228 2>; +}; + +test_timer: &timer21 { + status = "okay"; + interrupts = <203 1>; +}; + +&timer20 { + status = "okay"; + interrupts = <202 0>; +}; + +&timer00 { + status = "okay"; + prescaler = <0>; +}; + +/ { + chosen { + zephyr,cpu-load-counter = &timer00; + }; + + busy-sim { + compatible = "vnd,busy-sim"; + status = "okay"; + counter = <&timer20>; + }; +}; diff --git a/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay new file mode 100644 index 000000000000..cfa72ed02736 --- /dev/null +++ b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&grtc { + /*interrupts = <226 2>;*/ +}; + +test_timer: &timer21 { + status = "okay"; + /*interrupts = <203 2>;*/ +}; + +&timer20 { + status = "okay"; + interrupts = <202 0>; +}; + +&timer00 { + status = "okay"; + prescaler = <0>; +}; + +/ { + chosen { + zephyr,cpu-load-counter = &timer00; + }; + + busy-sim { + compatible = "vnd,busy-sim"; + status = "okay"; + counter = <&timer20>; + }; +}; diff --git a/tests/drivers/timer/nrf_grtc_timer/prj.conf b/tests/drivers/timer/nrf_grtc_timer/prj.conf index dea03477519d..93926f090b7e 100644 --- a/tests/drivers/timer/nrf_grtc_timer/prj.conf +++ b/tests/drivers/timer/nrf_grtc_timer/prj.conf @@ -1,2 +1,8 @@ CONFIG_ZTEST=y CONFIG_NRF_GRTC_TIMER=y +CONFIG_COUNTER=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_XOSHIRO_RANDOM_GENERATOR=y +CONFIG_LOG_PRINTK=y +CONFIG_CPU_LOAD=y +CONFIG_CPU_LOAD_USE_COUNTER=y diff --git a/tests/drivers/timer/nrf_grtc_timer/src/main.c b/tests/drivers/timer/nrf_grtc_timer/src/main.c index cede54f026f1..bcb57519f3b4 100644 --- a/tests/drivers/timer/nrf_grtc_timer/src/main.c +++ b/tests/drivers/timer/nrf_grtc_timer/src/main.c @@ -5,7 +5,15 @@ */ #include #include +#include +#include +#include +#include +#include +#include +#include #include +LOG_MODULE_REGISTER(test, 1); #define GRTC_SLEW_TICKS 10 #define NUMBER_OF_TRIES 2000 @@ -153,4 +161,250 @@ ZTEST(nrf_grtc_timer, test_timer_abort_in_compare_mode) z_nrf_grtc_timer_chan_free(channel); } +enum test_timer_state { + TIMER_IDLE, + TIMER_PREPARE, + TIMER_ACTIVE +}; + +enum test_ctx { + TEST_HIGH_PRI, + TEST_TIMER_CB, + TEST_THREAD +}; + +struct test_grtc_timer { + struct k_timer timer; + uint32_t ticks; + uint32_t expire; + uint32_t start_cnt; + uint32_t expire_cnt; + uint32_t abort_cnt; + uint32_t exp_expire; + int max_late; + int min_late; + int avg_late; + uint32_t early_cnt; + enum test_timer_state state; +}; + +static atomic_t test_active_cnt; +static struct test_grtc_timer timers[8]; +static uint32_t test_end; +static k_tid_t test_tid; +static volatile bool test_run; +static uint32_t ctx_cnt[3]; +static const char *const ctx_name[] = { "HIGH PRIO ISR", "TIMER CALLBACK", "THREAD" }; + +static bool stress_test_action(int ctx, int id) +{ + struct test_grtc_timer *timer = &timers[id]; + + ctx_cnt[ctx]++; + if (timer->state == TIMER_ACTIVE) { + /* Aborting soon to expire timers from higher interrupt priority may lead + * to test failures. + */ + if (ctx == 0 && (k_timer_remaining_get(&timer->timer) < 5)) { + return true; + } + + if (timer->abort_cnt < timer->expire_cnt / 2) { + bool any_active; + + timer->state = TIMER_PREPARE; + k_timer_stop(&timer->timer); + timer->abort_cnt++; + any_active = atomic_dec(&test_active_cnt) > 1; + timer->state = TIMER_IDLE; + + return any_active; + } + } else if (timer->state == TIMER_IDLE) { + int ticks = 10 + (sys_rand32_get() & 0x3F); + k_timeout_t t = K_TICKS(ticks); + + timer->state = TIMER_PREPARE; + timer->exp_expire = k_ticks_to_cyc_floor32(sys_clock_tick_get_32() + ticks); + timer->ticks = ticks; + k_timer_start(&timer->timer, t, K_NO_WAIT); + atomic_inc(&test_active_cnt); + timer->start_cnt++; + timer->state = TIMER_ACTIVE; + } + + return true; +} + +static void stress_test_actions(int ctx) +{ + uint32_t r = sys_rand32_get(); + int action_cnt = Z_MAX(r & 0x3, 1); + int tmr_id = (r >> 8) % ARRAY_SIZE(timers); + + /* Occasionally wake thread context from which timer actions are also executed. */ + if ((((r >> 2) & 0x3) == 0) || test_active_cnt < 2) { + LOG_DBG("ctx:%d thread wakeup", ctx); + k_wakeup(test_tid); + } + + for (int i = 0; i < action_cnt; i++) { + if (stress_test_action(ctx, tmr_id) == false) { + stress_test_action(ctx, tmr_id); + } + } +} + +static void timer_cb(struct k_timer *timer) +{ + struct test_grtc_timer *test_timer = CONTAINER_OF(timer, struct test_grtc_timer, timer); + uint32_t now = k_cycle_get_32(); + int diff = now - test_timer->exp_expire; + + atomic_dec(&test_active_cnt); + zassert_true(diff >= 0); + test_timer->max_late = MAX(diff, test_timer->max_late); + test_timer->min_late = MIN(diff, test_timer->min_late); + + if (test_timer->expire_cnt == 0) { + test_timer->avg_late = diff; + } else { + test_timer->avg_late = (test_timer->avg_late * test_timer->expire_cnt + diff) / + (test_timer->expire_cnt + 1); + } + + test_timer->expire_cnt++; + test_timer->state = TIMER_IDLE; + + if (test_run) { + stress_test_actions(TEST_TIMER_CB); + } +} + +static void counter_set(const struct device *dev, struct counter_alarm_cfg *cfg) +{ + int err; + uint32_t us = 150 + (sys_rand32_get() & 0x3F); + + cfg->ticks = counter_us_to_ticks(dev, us); + err = counter_set_channel_alarm(dev, 0, cfg); + zassert_equal(err, 0); +} + +static void counter_cb(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *user_data) +{ + struct counter_alarm_cfg *config = user_data; + + if (test_run) { + stress_test_actions(TEST_HIGH_PRI); + counter_set(dev, config); + } +} + +static void report_progress(uint32_t start, uint32_t end) +{ + static uint32_t next_report; + static uint32_t step; + static uint32_t progress; + + if (next_report == 0) { + step = (end - start) / 10; + next_report = start + step; + } + + if (k_uptime_get_32() > next_report) { + next_report += step; + progress += 10; + printk("%d%%\r", progress); + } +} + +static void grtc_stress_test(bool busy_sim_en) +{ + static struct counter_alarm_cfg alarm_cfg; +#if DT_NODE_EXISTS(DT_NODELABEL(test_timer)) && DT_NODE_HAS_STATUS(DT_NODELABEL(test_timer), okay) + const struct device *const counter_dev = DEVICE_DT_GET(DT_NODELABEL(test_timer)); +#else + const struct device *const counter_dev = NULL; +#endif + uint32_t test_ms = 5000; + uint32_t test_start = k_uptime_get_32(); + uint32_t load; + + test_end = k_cycle_get_32() + k_ms_to_cyc_floor32(test_ms); + test_tid = k_current_get(); + + for (size_t i = 0; i < ARRAY_SIZE(timers); i++) { + k_timer_init(&timers[i].timer, timer_cb, NULL); + } + + if (IS_ENABLED(CONFIG_CPU_LOAD)) { + (void)cpu_load_get(true); + } + + if (counter_dev) { + counter_start(counter_dev); + } + + alarm_cfg.callback = counter_cb; + alarm_cfg.user_data = &alarm_cfg; + test_run = true; + + if (counter_dev) { + counter_set(counter_dev, &alarm_cfg); + } + + if (busy_sim_en) { + busy_sim_start(500, 200, 1000, 400, NULL); + } + + LOG_DBG("Starting test, will end at %d", test_end); + while (k_cycle_get_32() < test_end) { + report_progress(test_start, test_start + test_ms); + stress_test_actions(TEST_THREAD); + k_sleep(K_MSEC(test_ms)); + } + + load = IS_ENABLED(CONFIG_CPU_LOAD) ? cpu_load_get(true) : 0; + + test_run = false; + k_msleep(50); + + for (size_t i = 0; i < ARRAY_SIZE(timers); i++) { + zassert_equal(timers[i].state, TIMER_IDLE, "Unexpected timer %d state:%d", + i, timers[i].state); + TC_PRINT("Timer%d (%p)\r\n\tstart_cnt:%d abort_cnt:%d expire_cnt:%d\n", + i, &timers[i], timers[i].start_cnt, timers[i].abort_cnt, + timers[i].expire_cnt); + TC_PRINT("\tavarage late:%d ticks, max late:%d, min late:%d early:%d\n", + timers[i].avg_late, timers[i].max_late, timers[i].min_late, + timers[i].early_cnt); + } + + for (size_t i = 0; i < ARRAY_SIZE(ctx_cnt); i++) { + TC_PRINT("Context: %s executed %d times\n", ctx_name[i], ctx_cnt[i]); + } + TC_PRINT("CPU load during test:%d.%d\n", load / 10, load % 10); + + if (busy_sim_en) { + busy_sim_stop(); + } + + if (counter_dev) { + counter_stop(counter_dev); + } + +#ifdef CONFIG_COVERAGE + /* Wait a few seconds before exit, giving the test the + * opportunity to dump some output before coverage data gets emitted + */ + k_sleep(K_MSEC(5000)); +#endif +} + +ZTEST(nrf_grtc_timer, test_stress) +{ + grtc_stress_test(false); +} + ZTEST_SUITE(nrf_grtc_timer, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/timer/nrf_grtc_timer/testcase.yaml b/tests/drivers/timer/nrf_grtc_timer/testcase.yaml index 6f4486de913c..549234220ceb 100644 --- a/tests/drivers/timer/nrf_grtc_timer/testcase.yaml +++ b/tests/drivers/timer/nrf_grtc_timer/testcase.yaml @@ -1,17 +1,23 @@ +common: + tags: + - drivers + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad + - nrf54h20dk/nrf54h20/cpuppr + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns + - nrf54l15dk/nrf54l15/cpuflpr + - nrf54l15bsim/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr + - ophelia4ev/nrf54l15/cpuapp + - ophelia4ev/nrf54l15/cpuflpr + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp + timeout: 30 tests: - drivers.timer.nrf_grtc_timer: - tags: drivers - platform_allow: - - nrf54h20dk/nrf54h20/cpuapp - - nrf54h20dk/nrf54h20/cpurad - - nrf54h20dk/nrf54h20/cpuppr - - nrf54l15dk/nrf54l15/cpuapp - - nrf54l15dk/nrf54l15/cpuflpr - - nrf54l15bsim/nrf54l15/cpuapp - - nrf54lm20dk/nrf54lm20a/cpuapp - - nrf54lm20dk/nrf54lm20a/cpuflpr - - ophelia4ev/nrf54l15/cpuapp - - ophelia4ev/nrf54l15/cpuflpr - integration_platforms: - - nrf54lm20dk/nrf54lm20a/cpuapp - timeout: 30 + drivers.timer.nrf_grtc_timer: {} + drivers.timer.nrf_grtc_timer.no_assert: + extra_configs: + - CONFIG_ASSERT=n diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf new file mode 100644 index 000000000000..47f481017118 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf @@ -0,0 +1,3 @@ +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y +CONFIG_VAR_LENGTH_BUFFER_TEST_BUADRATE_LIMIT=57600 diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuppr_xip.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuppr_xip.overlay new file mode 100644 index 000000000000..f65b4dd3b0ba --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuppr_xip.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index a1e29cbf0ffc..d8995e369711 100644 --- a/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -42,6 +42,7 @@ dut: &uart21 { pinctrl-1 = <&uart21_sleep_alt>; pinctrl-names = "default", "sleep"; current-speed = <115200>; + timer = <&timer21>; }; dut2: &uart00 { diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.conf b/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.conf new file mode 100644 index 000000000000..d70069646c93 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.conf @@ -0,0 +1 @@ +CONFIG_VAR_LENGTH_BUFFER_TEST_BUADRATE_LIMIT=57600 diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/uart/uart_async_dual/Kconfig b/tests/drivers/uart/uart_async_dual/Kconfig index 6e80ec3a7957..f0087aa48e3b 100644 --- a/tests/drivers/uart/uart_async_dual/Kconfig +++ b/tests/drivers/uart/uart_async_dual/Kconfig @@ -16,5 +16,13 @@ config PM_RUNTIME_IN_TEST select PM_DEVICE select PM_DEVICE_RUNTIME +config TEST_CHOPPED_TX + bool "Test chopped TX data" + default y + help + When enabled then test cases that transmits TX packets in random chunks are + performed. Some driver implementation do not support case when new TX data + collides with handling of the RX timeout. + # Include Zephyr's Kconfig source "Kconfig" diff --git a/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_common.dtsi index e651cf5399ed..1ca0775f629e 100644 --- a/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_common.dtsi +++ b/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -60,6 +60,16 @@ }; }; +&timer134 { + status = "reserved"; +}; + +&dppic135 { + owned-channels = <0>; + source-channels = <0>; + status = "okay"; +}; + dut: &uart134 { status = "okay"; current-speed = <115200>; @@ -67,6 +77,7 @@ dut: &uart134 { pinctrl-1 = <&uart134_alt_sleep>; pinctrl-names = "default", "sleep"; hw-flow-control; + timer = <&timer134>; zephyr,pm-device-runtime-auto; }; @@ -80,12 +91,23 @@ dut_aux: &uart137 { zephyr,pm-device-runtime-auto; }; +&dppic120 { + owned-channels = <0>; + source-channels = <0>; + status = "okay"; +}; + +&timer120 { + status = "reserved"; +}; + dut2: &uart120 { pinctrl-0 = <&uart120_default_alt>; pinctrl-1 = <&uart120_sleep_alt>; pinctrl-names = "default", "sleep"; current-speed = <115200>; hw-flow-control; + timer = <&timer120>; zephyr,pm-device-runtime-auto; }; diff --git a/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_cpuapp.conf index 6dffc1fe4e19..74cc8d7691e1 100644 --- a/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -1,3 +1,2 @@ CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_CLOCK_CONTROL=y diff --git a/tests/drivers/uart/uart_async_dual/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/uart/uart_async_dual/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index 93ad73f3b373..224399ccaa95 100644 --- a/tests/drivers/uart/uart_async_dual/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/uart/uart_async_dual/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -38,6 +38,10 @@ }; }; +&timer21 { + status = "reserved"; +}; + dut: &uart21 { status = "okay"; current-speed = <115200>; @@ -45,6 +49,8 @@ dut: &uart21 { pinctrl-1 = <&uart21_sleep>; pinctrl-names = "default", "sleep"; hw-flow-control; + timer = <&timer21>; + zephyr,pm-device-runtime-auto; }; dut_aux: &uart22 { @@ -54,6 +60,7 @@ dut_aux: &uart22 { pinctrl-1 = <&uart22_sleep>; pinctrl-names = "default", "sleep"; hw-flow-control; + zephyr,pm-device-runtime-auto; }; &timer20 { diff --git a/tests/drivers/uart/uart_async_dual/src/main.c b/tests/drivers/uart/uart_async_dual/src/main.c index 37ce73120acb..160d8c761040 100644 --- a/tests/drivers/uart/uart_async_dual/src/main.c +++ b/tests/drivers/uart/uart_async_dual/src/main.c @@ -28,9 +28,10 @@ LOG_MODULE_REGISTER(test); #endif #define TX_TIMEOUT 100000 -#define RX_TIMEOUT 2000 +#define RX_TIMEOUT_BYTES 50 #define MAX_PACKET_LEN 128 +#define MIN_PACKET_LEN 10 struct dut_data { const struct device *dev; @@ -60,6 +61,25 @@ ZTEST_DMEM struct dut_data duts[] = { #endif }; +/* Array that contains potential payload. It is used to memcmp against incoming packets. */ +static const uint8_t test_buf[256] = { + 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, + 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, + 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, + 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, + 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, + 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, + 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, + 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, + 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, + 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, + 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, + 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, + 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + static void pm_check(const struct device *dev, const struct device *second_dev, bool exp_on, int line) { @@ -100,6 +120,7 @@ static const struct device *tx_dev; enum test_tx_mode { TX_BULK, TX_PACKETS, + TX_CHOPPED, }; struct test_tx_data { @@ -111,6 +132,8 @@ struct test_tx_data { volatile bool cont; volatile enum test_tx_mode mode; struct k_sem sem; + uint32_t idx; + uint32_t rx_timeout; }; enum test_rx_state { @@ -121,17 +144,24 @@ enum test_rx_state { enum test_rx_mode { RX_CONT, RX_DIS, + RX_ALL, }; +typedef bool (*test_on_rx_rdy_t)(const struct device *dev, uint8_t *buf, size_t len); + struct test_rx_data { uint8_t hdr[1]; uint8_t buf[256]; uint32_t rx_cnt; + uint32_t payload_idx; enum test_rx_state state; enum test_rx_mode mode; volatile bool cont; bool buf_req; struct k_sem sem; + uint32_t timeout; + uint32_t buf_idx; + test_on_rx_rdy_t on_rx_rdy; }; static struct test_tx_data tx_data; @@ -143,8 +173,8 @@ static void fill_tx(struct test_tx_data *data) uint32_t len; int err; - if (data->mode == TX_PACKETS) { - err = k_sem_take(&data->sem, K_MSEC(100)); + if (data->mode != TX_BULK) { + err = k_sem_take(&data->sem, K_MSEC(200)); if (err < 0 && !data->cont) { return; } @@ -153,9 +183,10 @@ static void fill_tx(struct test_tx_data *data) uint8_t len = sys_rand8_get(); len = len % MAX_PACKET_LEN; - len = MAX(2, len); + len = MAX(MIN_PACKET_LEN, len); data->packet_len = len; + data->idx = 0; for (int i = 0; i < len; i++) { data->buf[i] = len - i; } @@ -163,12 +194,11 @@ static void fill_tx(struct test_tx_data *data) return; } - while ((len = ring_buf_put_claim(&data->rbuf, &buf, 255)) > 1) { + while ((len = ring_buf_put_claim(&data->rbuf, &buf, 255)) > 0) { uint8_t r = (sys_rand8_get() % MAX_PACKET_LEN) % len; - uint8_t packet_len = MAX(r, 2); - uint8_t rem = len - packet_len; + uint8_t packet_len = MAX(r, MIN_PACKET_LEN); - packet_len = (rem < 3) ? len : packet_len; + packet_len = (len <= MIN_PACKET_LEN) ? len : packet_len; buf[0] = packet_len; for (int i = 1; i < packet_len; i++) { buf[i] = packet_len - i; @@ -189,7 +219,7 @@ static void try_tx(const struct device *dev, bool irq) return; } - if ((tx_data.mode == TX_PACKETS) && (tx_data.packet_len > 0)) { + if (tx_data.mode == TX_PACKETS) { uint8_t len = tx_data.packet_len; tx_data.packet_len = 0; @@ -199,19 +229,50 @@ static void try_tx(const struct device *dev, bool irq) err, irq, tx_data.cont); return; } - zassert_true(tx_data.mode == TX_BULK); - if (!atomic_cas(&tx_data.busy, 0, 1)) { + if (tx_data.mode == TX_BULK) { + if (!atomic_cas(&tx_data.busy, 0, 1)) { + return; + } + + len = ring_buf_get_claim(&tx_data.rbuf, &buf, 255); + if (len > 0) { + err = uart_tx(dev, buf, len, TX_TIMEOUT); + zassert_equal(err, 0, + "Unexpected err:%d irq:%d cont:%d\n", + err, irq, tx_data.cont); + } else { + tx_data.busy = 0; + } return; } - len = ring_buf_get_claim(&tx_data.rbuf, &buf, 255); - if (len > 0) { - err = uart_tx(dev, buf, len, TX_TIMEOUT); - zassert_equal(err, 0, - "Unexpected err:%d irq:%d cont:%d\n", - err, irq, tx_data.cont); + zassert_true(tx_data.mode == TX_CHOPPED); + + uint32_t rem = tx_data.packet_len - tx_data.idx; + + if (tx_data.packet_len > 12) { + len = sys_rand8_get() % (tx_data.packet_len / 4); + } else { + len = 0; } + len = MAX(3, len); + len = MIN(rem, len); + + buf = &tx_data.buf[tx_data.idx]; + tx_data.idx += len; + + err = uart_tx(dev, buf, len, TX_TIMEOUT); + zassert_equal(err, 0, + "Unexpected err:%d irq:%d cont:%d\n", + err, irq, tx_data.cont); +} + +static void tx_backoff(uint32_t rx_timeout) +{ + uint32_t delay = (rx_timeout / 2) + (sys_rand32_get() % rx_timeout); + + k_busy_wait(delay); } static void on_tx_done(const struct device *dev, struct uart_event *evt) @@ -221,61 +282,117 @@ static void on_tx_done(const struct device *dev, struct uart_event *evt) return; } + if (tx_data.mode == TX_CHOPPED) { + if (tx_data.idx == tx_data.packet_len) { + k_sem_give(&tx_data.sem); + } else { + + tx_backoff(tx_data.rx_timeout); + try_tx(dev, true); + } + return; + } + /* Finish previous data chunk and start new if any pending. */ ring_buf_get_finish(&tx_data.rbuf, evt->data.tx.len); atomic_set(&tx_data.busy, 0); try_tx(dev, true); } -static void on_rx_rdy(const struct device *dev, struct uart_event *evt) +static bool on_rx_rdy_rx_all(const struct device *dev, uint8_t *buf, size_t len) { - uint32_t len = evt->data.rx.len; - uint32_t off = evt->data.rx.offset; - int err; + bool ok; - if (!rx_data.cont) { - return; + if (rx_data.payload_idx == 0) { + rx_data.payload_idx = buf[0] - 1; + buf++; + len--; } - rx_data.rx_cnt += evt->data.rx.len; - if (evt->data.rx.buf == rx_data.hdr) { - rx_data.state = RX_PAYLOAD; - if ((rx_data.mode == RX_CONT) && rx_data.buf_req) { - size_t l = rx_data.hdr[0] - 1; + ok = memcmp(buf, &test_buf[256 - rx_data.payload_idx], len) == 0; + rx_data.payload_idx -= len; - zassert_true(l > 0); - rx_data.buf_req = false; - err = uart_rx_buf_rsp(dev, rx_data.buf, rx_data.hdr[0] - 1); - } - } else { - /* Payload received */ - rx_data.state = RX_HDR; - zassert_equal(len, rx_data.hdr[0] - 1); + return ok; +} - for (int i = 0; i < len; i++) { - bool ok = evt->data.rx.buf[off + i] == (uint8_t)(len - i); +static bool on_rx_rdy_hdr(const struct device *dev, uint8_t *buf, size_t len); - if (!ok) { - LOG_ERR("Unexpected data at %d, exp:%02x got:%02x", - i, len - i, evt->data.rx.buf[off + i]); - } +static bool on_rx_rdy_payload(const struct device *dev, uint8_t *buf, size_t len) +{ + bool ok; + int err; - zassert_true(ok, "Unexpected data at %d, exp:%02x got:%02x", - i, len - i, evt->data.rx.buf[off + i]); - if (!ok) { - rx_data.cont = false; - tx_data.cont = false; - /* Avoid flood of errors as we are in the interrupt and ztest - * cannot abort from here. - */ - return; + ok = memcmp(buf, &test_buf[255 - rx_data.payload_idx], len) == 0; + if (!ok) { + for (int i = 0; i < len; i++) { + if (buf[i] != test_buf[255 - rx_data.payload_idx + i]) { + zassert_true(false, "Byte %d expected: %02x got: %02x", + i, buf[i], test_buf[255 - rx_data.payload_idx + i]); } } + rx_data.cont = false; + tx_data.cont = false; + zassert_true(ok); + return false; + } + + rx_data.payload_idx -= len; + + if (rx_data.payload_idx == 0) { + rx_data.state = RX_HDR; + rx_data.on_rx_rdy = on_rx_rdy_hdr; if ((rx_data.mode == RX_CONT) && rx_data.buf_req) { rx_data.buf_req = false; err = uart_rx_buf_rsp(dev, rx_data.hdr, 1); + zassert_equal(err, 0); } } + + return true; +} + +static bool on_rx_rdy_hdr(const struct device *dev, uint8_t *buf, size_t len) +{ + int err; + + zassert_equal(buf, rx_data.hdr); + zassert_equal(len, 1); + if (rx_data.hdr[0] == 1) { + /* single byte packet. */ + if ((rx_data.mode == RX_CONT) && rx_data.buf_req) { + err = uart_rx_buf_rsp(dev, rx_data.hdr, 1); + zassert_equal(err, 0); + } + return true; + } + + zassert_equal(rx_data.payload_idx, 0); + rx_data.on_rx_rdy = on_rx_rdy_payload; + rx_data.payload_idx = rx_data.hdr[0] - 1; + rx_data.state = RX_PAYLOAD; + if ((rx_data.mode == RX_CONT) && rx_data.buf_req) { + size_t l = rx_data.hdr[0] - 1; + + zassert_true(l > 0); + rx_data.buf_req = false; + err = uart_rx_buf_rsp(dev, rx_data.buf, buf[0] - 1); + } + + return true; +} + +static void on_rx_buf_req(const struct device *dev) +{ + if (rx_data.mode != RX_ALL) { + rx_data.buf_req = true; + return; + } + + size_t len = sizeof(rx_data.buf) / 2; + uint8_t *buf = &rx_data.buf[len * rx_data.buf_idx]; + + rx_data.buf_idx = (rx_data.buf_idx + 1) & 0x1; + uart_rx_buf_rsp(dev, buf, len); } static void on_rx_dis(const struct device *dev, struct uart_event *evt, void *user_data) @@ -283,8 +400,17 @@ static void on_rx_dis(const struct device *dev, struct uart_event *evt, void *us ARG_UNUSED(evt); struct test_rx_data *data = user_data; int err; - uint8_t *buf = (data->state == RX_HDR) ? data->hdr : data->buf; - uint32_t len = (data->state == RX_HDR) ? 1 : (data->hdr[0] - 1); + uint8_t *buf; + uint32_t len; + + if (data->mode == RX_ALL) { + buf = data->buf; + len = sizeof(data->buf) / 2; + } else { + buf = (data->state == RX_HDR) ? data->hdr : data->buf; + len = (data->state == RX_HDR) ? 1 : (data->hdr[0] - 1); + data->buf_idx = 1; + } data->buf_req = false; @@ -292,9 +418,8 @@ static void on_rx_dis(const struct device *dev, struct uart_event *evt, void *us return; } - zassert_true(len > 0); - err = uart_rx_enable(dev, buf, len, RX_TIMEOUT); + err = uart_rx_enable(dev, buf, len, data->timeout); zassert_equal(err, 0, "Unexpected err:%d", err); } @@ -324,14 +449,18 @@ static void uart_callback(const struct device *dev, struct uart_event *evt, void break; case UART_RX_RDY: zassert_true(dev == rx_dev); - on_rx_rdy(dev, evt); + if (rx_data.cont) { + rx_data.on_rx_rdy(dev, &evt->data.rx.buf[evt->data.rx.offset], + evt->data.rx.len); + rx_data.rx_cnt += evt->data.rx.len; + } break; case UART_RX_BUF_RELEASED: zassert_true(dev == rx_dev); break; case UART_RX_BUF_REQUEST: - rx_data.buf_req = true; zassert_true(dev == rx_dev); + on_rx_buf_req(dev); break; case UART_RX_DISABLED: zassert_true(dev == rx_dev); @@ -346,7 +475,7 @@ static void uart_callback(const struct device *dev, struct uart_event *evt, void } } -static void config_baudrate(uint32_t rate) +static void config_baudrate(uint32_t rate, bool hwfc) { struct uart_config config; int err; @@ -354,6 +483,7 @@ static void config_baudrate(uint32_t rate) err = uart_config_get(rx_dev, &config); zassert_equal(err, 0, "Unexpected err:%d", err); + config.flow_ctrl = hwfc ? UART_CFG_FLOW_CTRL_RTS_CTS : UART_CFG_FLOW_CTRL_NONE; config.baudrate = rate; err = uart_configure(rx_dev, &config); @@ -365,6 +495,26 @@ static void config_baudrate(uint32_t rate) } } +static void report_progress(uint32_t start) +{ + static const uint32_t inc = CONFIG_UART_ASYNC_DUAL_TEST_TIMEOUT / 20; + static uint32_t next; + static uint32_t progress; + + if ((k_uptime_get_32() - start < inc) && progress) { + /* Reset state. */ + next = inc; + progress = 0; + } + + if (k_uptime_get_32() > (start + next)) { + progress += 5; + TC_PRINT("\r%d%%", progress); + next += inc; + } +} + + /* Test is running following scenario. Transmitter is sending packets which * has 1 byte header with length followed by the payload. Transmitter can send * packets in two modes: bulk where data is send in chunks without gaps between @@ -376,12 +526,14 @@ static void config_baudrate(uint32_t rate) * * Test has busy simulator running if it is enabled in the configuration. */ -static void var_packet_hwfc(uint32_t baudrate, bool tx_packets, bool cont) +static void var_packet(uint32_t baudrate, enum test_tx_mode tx_mode, + enum test_rx_mode rx_mode, bool hwfc) { int err; uint32_t load = 0; + uint32_t start = k_uptime_get_32(); - config_baudrate(baudrate); + config_baudrate(baudrate, hwfc); if (IS_ENABLED(CONFIG_TEST_BUSY_SIM)) { uint32_t active_avg = (baudrate == 1000000) ? 5 : 30; @@ -393,13 +545,15 @@ static void var_packet_hwfc(uint32_t baudrate, bool tx_packets, bool cont) memset(&tx_data, 0, sizeof(tx_data)); memset(&rx_data, 0, sizeof(rx_data)); tx_data.cont = true; - tx_data.mode = tx_packets ? TX_PACKETS : TX_BULK; - k_sem_init(&tx_data.sem, tx_packets ? 1 : 0, 1); + tx_data.mode = tx_mode; + k_sem_init(&tx_data.sem, (tx_mode != TX_BULK) ? 1 : 0, 1); + rx_data.timeout = (RX_TIMEOUT_BYTES * 1000000 * 10) / baudrate; + tx_data.rx_timeout = rx_data.timeout; rx_data.cont = true; rx_data.rx_cnt = 0; - rx_data.state = RX_HDR; - rx_data.mode = cont ? RX_CONT : RX_DIS; + rx_data.on_rx_rdy = rx_mode == RX_ALL ? on_rx_rdy_rx_all : on_rx_rdy_hdr; + rx_data.mode = rx_mode; ring_buf_init(&tx_data.rbuf, sizeof(tx_data.buf), tx_data.buf); @@ -420,8 +574,10 @@ static void var_packet_hwfc(uint32_t baudrate, bool tx_packets, bool cont) while (tx_data.cont || rx_data.cont) { fill_tx(&tx_data); k_msleep(1); + report_progress(start); try_tx(tx_dev, false); } + TC_PRINT("\n"); if (IS_ENABLED(CONFIG_CPU_LOAD)) { load = cpu_load_get(true); @@ -436,62 +592,82 @@ static void var_packet_hwfc(uint32_t baudrate, bool tx_packets, bool cont) /* Flush all TX data that may be already started. */ k_msleep(10); - (void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), RX_TIMEOUT); + (void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), rx_data.timeout); k_msleep(10); (void)uart_rx_disable(rx_dev); k_msleep(10); TC_PRINT("Received %d bytes for %d ms, CPU load:%d.%d\n", rx_data.rx_cnt, CONFIG_UART_ASYNC_DUAL_TEST_TIMEOUT, load / 10, load % 10); - zassert_true(rx_data.rx_cnt > 1000, "Unexected RX cnt: %d", rx_data.rx_cnt); + zassert_true(rx_data.rx_cnt > 1000, "Unexpected RX cnt: %d", rx_data.rx_cnt); } ZTEST(uart_async_dual, test_var_packets_tx_bulk_dis_hwfc) { /* TX in bulk mode, RX in DIS mode, 115k2 */ - var_packet_hwfc(115200, false, false); + var_packet(115200, TX_BULK, RX_DIS, true); } ZTEST(uart_async_dual, test_var_packets_tx_bulk_cont_hwfc) { /* TX in bulk mode, RX in CONT mode, 115k2 */ - var_packet_hwfc(115200, false, true); + var_packet(115200, TX_BULK, RX_CONT, true); } ZTEST(uart_async_dual, test_var_packets_tx_bulk_dis_hwfc_1m) { /* TX in bulk mode, RX in DIS mode, 1M */ - var_packet_hwfc(1000000, false, false); + var_packet(1000000, TX_BULK, RX_DIS, true); } ZTEST(uart_async_dual, test_var_packets_tx_bulk_cont_hwfc_1m) { /* TX in bulk mode, RX in CONT mode, 1M */ - var_packet_hwfc(1000000, false, true); + var_packet(1000000, TX_BULK, RX_CONT, true); } ZTEST(uart_async_dual, test_var_packets_dis_hwfc) { /* TX in packet mode, RX in DIS mode, 115k2 */ - var_packet_hwfc(115200, true, false); + var_packet(115200, TX_PACKETS, RX_DIS, true); } ZTEST(uart_async_dual, test_var_packets_cont_hwfc) { /* TX in packet mode, RX in CONT mode, 115k2 */ - var_packet_hwfc(115200, true, true); + var_packet(115200, TX_PACKETS, RX_CONT, true); } ZTEST(uart_async_dual, test_var_packets_dis_hwfc_1m) { /* TX in packet mode, RX in DIS mode, 1M */ - var_packet_hwfc(1000000, true, false); + var_packet(1000000, TX_PACKETS, RX_DIS, true); } ZTEST(uart_async_dual, test_var_packets_cont_hwfc_1m) { /* TX in packet mode, RX in CONT mode, 1M */ - var_packet_hwfc(1000000, true, true); + var_packet(1000000, TX_PACKETS, RX_CONT, true); +} + +ZTEST(uart_async_dual, test_var_packets_chopped_all) +{ + if (!IS_ENABLED(CONFIG_TEST_CHOPPED_TX)) { + ztest_test_skip(); + } + + /* TX in chopped mode, RX in receive ALL mode, 115k2 */ + var_packet(115200, TX_CHOPPED, RX_ALL, false); +} + +ZTEST(uart_async_dual, test_var_packets_chopped_all_1m) +{ + if (!IS_ENABLED(CONFIG_TEST_CHOPPED_TX)) { + ztest_test_skip(); + } + + /* TX in chopped mode, RX in receive ALL mode, 1M */ + var_packet(1000000, TX_CHOPPED, RX_ALL, false); } static void hci_like_callback(const struct device *dev, struct uart_event *evt, void *user_data) @@ -540,7 +716,7 @@ static bool rx(uint8_t *buf, size_t len) { int err; - err = uart_rx_enable(rx_dev, buf, len, RX_TIMEOUT); + err = uart_rx_enable(rx_dev, buf, len, rx_data.timeout); zassert_equal(err, 0, "Unexpected err:%d", err); err = k_sem_take(&rx_data.sem, K_MSEC(100)); @@ -653,6 +829,7 @@ static void hci_like_rx(void) uint8_t len; bool cont; bool explicit_pm = IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST); + uint32_t start = k_uptime_get_32(); while (1) { if (explicit_pm) { @@ -704,7 +881,9 @@ static void hci_like_rx(void) PM_CHECK(rx_dev, tx_dev, false); check_payload(rx_data.buf, len); + report_progress(start); } + TC_PRINT("\n"); } #define HCI_LIKE_TX_STACK_SIZE 2048 @@ -725,7 +904,7 @@ static void hci_like_test(uint32_t baudrate) int err; uint32_t load = 0; - config_baudrate(baudrate); + config_baudrate(baudrate, true); if (IS_ENABLED(CONFIG_TEST_BUSY_SIM)) { uint32_t active_avg = (baudrate == 1000000) ? 10 : 50; @@ -739,6 +918,7 @@ static void hci_like_test(uint32_t baudrate) tx_data.cnt = 0; tx_data.cont = true; rx_data.cont = true; + rx_data.timeout = (RX_TIMEOUT_BYTES * 1000000 * 10) / baudrate; k_sem_init(&tx_data.sem, 1, 1); k_sem_init(&rx_data.sem, 0, 1); @@ -776,7 +956,7 @@ static void hci_like_test(uint32_t baudrate) k_msleep(10); PM_CHECK(tx_dev, rx_dev, false); - (void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), RX_TIMEOUT); + (void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), rx_data.timeout); k_msleep(1); (void)uart_rx_disable(rx_dev); diff --git a/tests/drivers/uart/uart_async_dual/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/uart/uart_async_dual/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index fcdc838a54e4..65a2c52016e6 100644 --- a/tests/drivers/uart/uart_async_dual/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/uart/uart_async_dual/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -9,3 +9,15 @@ status = "reserved"; interrupt-parent = <&cpuppr_clic>; }; + +&timer134 { + interrupt-parent = <&cpuppr_clic>; +}; + +&dppic135 { + child-owned-channels = <0>; +}; + +&uart136 { + current-speed = <1000000>; +}; diff --git a/tests/drivers/uart/uart_async_dual/testcase.yaml b/tests/drivers/uart/uart_async_dual/testcase.yaml index 1a2d811bbfe9..1722d5e5e7d1 100644 --- a/tests/drivers/uart/uart_async_dual/testcase.yaml +++ b/tests/drivers/uart/uart_async_dual/testcase.yaml @@ -73,3 +73,18 @@ tests: - nrf52_bsim extra_configs: - CONFIG_PM_RUNTIME_IN_TEST=y + drivers.uart.async_dual.no_tx_chopped: + harness: ztest + harness_config: + fixture: uart_loopback + depends_on: gpio + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad + - nrf54h20dk/nrf54h20/cpuppr + - nrf9160dk/nrf9160 + - nrf52_bsim + extra_configs: + - CONFIG_TEST_CHOPPED_TX=n + - CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER=n diff --git a/tests/drivers/uart/uart_elementary/testcase.yaml b/tests/drivers/uart/uart_elementary/testcase.yaml index cd25f46c1415..b680e0f96428 100644 --- a/tests/drivers/uart/uart_elementary/testcase.yaml +++ b/tests/drivers/uart/uart_elementary/testcase.yaml @@ -100,3 +100,4 @@ tests: extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay" extra_configs: - CONFIG_NRF_SYS_EVENT=y + - CONFIG_SOC_NRF_FORCE_CONSTLAT=y diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..f1d1d387c2e0 --- /dev/null +++ b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15dk_nrf54l15_cpuapp.overlay" diff --git a/tests/drivers/watchdog/wdt_basic_api/testcase.yaml b/tests/drivers/watchdog/wdt_basic_api/testcase.yaml index 01b8e6d833a8..8ed81c715f90 100644 --- a/tests/drivers/watchdog/wdt_basic_api/testcase.yaml +++ b/tests/drivers/watchdog/wdt_basic_api/testcase.yaml @@ -26,8 +26,8 @@ tests: - panb611evb/nrf54l15/cpuflpr - panb611evb/nrf54l15/cpuflpr/xip - mimxrt700_evk/mimxrt798s/cm33_cpu1 - - nrf54l15dk/nrf54l15/cpuapp/ns - nrf54l15dk/nrf54l10/cpuapp/ns + - nrf54lm20dk/nrf54lm20a/cpuapp/ns - bl54l15_dvk/nrf54l10/cpuapp/ns - bl54l15_dvk/nrf54l15/cpuapp/ns - bl54l15u_dvk/nrf54l15/cpuapp/ns diff --git a/tests/kernel/pipe/deprecated/pipe_api/prj.conf b/tests/kernel/pipe/deprecated/pipe_api/prj.conf new file mode 100644 index 000000000000..df3270adfdf8 --- /dev/null +++ b/tests/kernel/pipe/deprecated/pipe_api/prj.conf @@ -0,0 +1,9 @@ +CONFIG_ZTEST=y +CONFIG_IRQ_OFFLOAD=y +CONFIG_TEST_USERSPACE=y +CONFIG_DYNAMIC_OBJECTS=y +CONFIG_MP_MAX_NUM_CPUS=1 +CONFIG_ZTEST_FATAL_HOOK=y +CONFIG_PIPES=y +CONFIG_DEPRECATION_TEST=y +CONFIG_MINIMAL_LIBC=y diff --git a/tests/kernel/sched/schedule_api/prj.conf b/tests/kernel/sched/schedule_api/prj.conf index a5ceef694331..8b649a3b7fca 100644 --- a/tests/kernel/sched/schedule_api/prj.conf +++ b/tests/kernel/sched/schedule_api/prj.conf @@ -7,3 +7,4 @@ CONFIG_MAX_THREAD_BYTES=6 CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y +CONFIG_MINIMAL_LIBC=y diff --git a/tests/kernel/sched/schedule_api/prj_multiq.conf b/tests/kernel/sched/schedule_api/prj_multiq.conf index c8dd4bf786bc..84c9d80ac619 100644 --- a/tests/kernel/sched/schedule_api/prj_multiq.conf +++ b/tests/kernel/sched/schedule_api/prj_multiq.conf @@ -7,3 +7,4 @@ CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y CONFIG_NUM_COOP_PRIORITIES=30 CONFIG_NUM_PREEMPT_PRIORITIES=40 +CONFIG_MINIMAL_LIBC=y diff --git a/tests/kernel/sleep/src/usleep.c b/tests/kernel/sleep/src/usleep.c index 8a234a27a199..a7c212e59b96 100644 --- a/tests/kernel/sleep/src/usleep.c +++ b/tests/kernel/sleep/src/usleep.c @@ -42,6 +42,11 @@ * loaded to its comparator. */ #define MAXIMUM_SHORTEST_TICKS 2 +#elif defined(CONFIG_SOC_NRF54H20_CPUPPR) && (CONFIG_SYS_CLOCK_TICKS_PER_SEC > 16384) +/* Similar for nRF54H20 cpuppr (RISC-V core), it has a slow CPU clock + * compared to other cores, causing the increased overhead. + */ +#define MAXIMUM_SHORTEST_TICKS 4 #else #define MAXIMUM_SHORTEST_TICKS 1 #endif diff --git a/tests/kernel/timer/timer_behavior/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf b/tests/kernel/timer/timer_behavior/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf new file mode 100644 index 000000000000..2e06babf30a7 --- /dev/null +++ b/tests/kernel/timer/timer_behavior/boards/nrf54h20dk_nrf54h20_cpuppr_xip.conf @@ -0,0 +1 @@ +CONFIG_SYS_CLOCK_TICKS_PER_SEC=3906 diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c index 98189ebe582c..6c154d6dd5e1 100644 --- a/tests/lib/devicetree/api/src/main.c +++ b/tests/lib/devicetree/api/src/main.c @@ -3271,13 +3271,7 @@ ZTEST(devicetree_api, test_fixed_partitions) /* Test DT_FIXED_PARTITION_ADDR. */ zassert_equal(DT_FIXED_PARTITION_ADDR(TEST_PARTITION_0), 0x20000000); zassert_equal(DT_FIXED_PARTITION_ADDR(TEST_PARTITION_1), 0x200000c0); - - /* DT_FIXED_PARTITION_ADDR(TEST_PARTITION_2) expands to an invalid expression. - * Test this by way of string comparison. - */ - zassert_true(!strcmp(TO_STRING(DT_FIXED_PARTITION_ADDR(TEST_PARTITION_2)), - "(__REG_IDX_0_VAL_ADDRESSU + 458624U)")); - zassert_equal(DT_REG_ADDR(TEST_PARTITION_2), 458624); + zassert_equal(DT_FIXED_PARTITION_ADDR(TEST_PARTITION_2), 0x33291080); /* Test that all DT_FIXED_PARTITION_ID are defined and unique. */ #define FIXED_PARTITION_ID_COMMA(node_id) DT_FIXED_PARTITION_ID(node_id), @@ -3312,6 +3306,9 @@ ZTEST(devicetree_api, test_fixed_subpartitions) zassert_true(DT_NODE_EXISTS(DT_MTD_FROM_FIXED_PARTITION(TEST_SUBPARTITION_COMBINED))); zassert_true(DT_NODE_EXISTS(DT_MTD_FROM_FIXED_SUBPARTITION(TEST_SUBPARTITION_0))); zassert_true(DT_NODE_EXISTS(DT_MTD_FROM_FIXED_SUBPARTITION(TEST_SUBPARTITION_1))); + zassert_true(DT_SAME_NODE( + DT_MTD_FROM_FIXED_PARTITION(TEST_SUBPARTITION_COMBINED), + DT_MTD_FROM_FIXED_SUBPARTITION(TEST_SUBPARTITION_1))); /* Test DT_FIXED_SUBPARTITION_ADDR. */ zassert_equal(DT_FIXED_PARTITION_ADDR(TEST_SUBPARTITION_COMBINED), 0x20000100); diff --git a/tests/lib/newlib/heap_listener/prj.conf b/tests/lib/newlib/heap_listener/prj.conf index e5a5dc6df4c1..7282777ff1ca 100644 --- a/tests/lib/newlib/heap_listener/prj.conf +++ b/tests/lib/newlib/heap_listener/prj.conf @@ -1,3 +1,4 @@ CONFIG_ZTEST=y CONFIG_NEWLIB_LIBC=y +CONFIG_NEWLIB_LIBC_NANO=n CONFIG_NEWLIB_LIBC_HEAP_LISTENER=y diff --git a/tests/net/ipv6/prj.conf b/tests/net/ipv6/prj.conf index 9f9f21d59050..6a6be5dba36a 100644 --- a/tests/net/ipv6/prj.conf +++ b/tests/net/ipv6/prj.conf @@ -33,6 +33,7 @@ CONFIG_NET_IF_MAX_IPV6_COUNT=2 CONFIG_NET_IPV6_PE=y CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT=2 CONFIG_NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES=n +CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y # Increase the stack a bit for mps2/an385 CONFIG_NET_RX_STACK_SIZE=1700 diff --git a/tests/net/socket/getaddrinfo/src/main.c b/tests/net/socket/getaddrinfo/src/main.c index c412cce87f41..25be0205ea87 100644 --- a/tests/net/socket/getaddrinfo/src/main.c +++ b/tests/net/socket/getaddrinfo/src/main.c @@ -96,7 +96,7 @@ static bool check_dns_query(uint8_t *buf, int buf_len) /* In this test we are just checking if the query came to us in correct * form, we are not creating a DNS server implementation here. */ - if (strncmp(result->data + 1, QUERY_HOST, + if (strncmp(result->data, QUERY_HOST, sizeof(QUERY_HOST) - 1)) { net_buf_unref(result); return false; diff --git a/tests/net/tcp/src/main.c b/tests/net/tcp/src/main.c index 2c0cfcd9ef2c..db57b70a40ef 100644 --- a/tests/net/tcp/src/main.c +++ b/tests/net/tcp/src/main.c @@ -116,6 +116,7 @@ static enum test_case_no { TEST_CLIENT_FIN_ACK_WITH_DATA = 18, TEST_CLIENT_SEQ_VALIDATION = 19, TEST_SERVER_ACK_VALIDATION = 20, + TEST_SERVER_FIN_ACK_AFTER_DATA = 21, } test_case_no; static enum test_state t_state; @@ -142,6 +143,7 @@ static void handle_syn_invalid_ack(sa_family_t af, struct tcphdr *th); static void handle_client_fin_ack_with_data_test(sa_family_t af, struct tcphdr *th); static void handle_client_seq_validation_test(sa_family_t af, struct tcphdr *th); static void handle_server_ack_validation_test(struct net_pkt *pkt); +static void handle_server_fin_ack_after_data_test(sa_family_t af, struct tcphdr *th); static void verify_flags(struct tcphdr *th, uint8_t flags, const char *fun, int line) @@ -494,6 +496,9 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt) case TEST_SERVER_ACK_VALIDATION: handle_server_ack_validation_test(pkt); break; + case TEST_SERVER_FIN_ACK_AFTER_DATA: + handle_server_fin_ack_after_data_test(net_pkt_family(pkt), &th); + break; default: zassert_true(false, "Undefined test case"); } @@ -3002,4 +3007,204 @@ ZTEST(net_tcp, test_server_ack_validation) net_context_put(accepted_ctx); } +#define TEST_FIN_ACK_AFTER_DATA_REQ "request" +#define TEST_FIN_ACK_AFTER_DATA_RSP "test data response" + +/* In this test we check that FIN,ACK packet acknowledging latest data is + * handled correctly by the TCP stack. + */ +static void handle_server_fin_ack_after_data_test(sa_family_t af, struct tcphdr *th) +{ + struct net_pkt *reply = NULL; + + zassert_false(th == NULL && t_state != T_SYN, + "NULL pkt only expected in T_SYN state"); + + switch (t_state) { + case T_SYN: + reply = prepare_syn_packet(af, htons(MY_PORT), htons(PEER_PORT)); + seq++; + t_state = T_SYN_ACK; + break; + case T_SYN_ACK: + test_verify_flags(th, SYN | ACK); + zassert_equal(ntohl(th->th_ack), seq, + "Unexpected ACK in T_SYN_ACK, got %d, expected %d", + ntohl(th->th_ack), seq); + device_initial_seq = ntohl(th->th_seq); + ack = ntohl(th->th_seq) + 1U; + t_state = T_DATA_ACK; + + /* Dummy "request" packet */ + reply = prepare_data_packet(af, htons(MY_PORT), htons(PEER_PORT), + TEST_FIN_ACK_AFTER_DATA_REQ, + sizeof(TEST_FIN_ACK_AFTER_DATA_REQ) - 1); + seq += sizeof(TEST_FIN_ACK_AFTER_DATA_REQ) - 1; + break; + case T_DATA_ACK: + test_verify_flags(th, ACK); + t_state = T_DATA; + zassert_equal(ntohl(th->th_seq), ack, + "Unexpected SEQ in T_DATA_ACK, got %d, expected %d", + get_rel_seq(th), ack); + zassert_equal(ntohl(th->th_ack), seq, + "Unexpected ACK in T_DATA_ACK, got %d, expected %d", + ntohl(th->th_ack), seq); + break; + case T_DATA: + test_verify_flags(th, PSH | ACK); + zassert_equal(ntohl(th->th_seq), ack, + "Unexpected SEQ in T_DATA, got %d, expected %d", + get_rel_seq(th), ack); + zassert_equal(ntohl(th->th_ack), seq, + "Unexpected ACK in T_DATA, got %d, expected %d", + ntohl(th->th_ack), seq); + ack += sizeof(TEST_FIN_ACK_AFTER_DATA_RSP) - 1; + t_state = T_FIN_ACK; + + reply = prepare_fin_ack_packet(af, htons(MY_PORT), htons(PEER_PORT)); + seq++; + break; + case T_FIN_ACK: + test_verify_flags(th, FIN | ACK); + zassert_equal(ntohl(th->th_seq), ack, + "Unexpected SEQ in T_FIN_ACK, got %d, expected %d", + get_rel_seq(th), ack); + zassert_equal(ntohl(th->th_ack), seq, + "Unexpected ACK in T_FIN_ACK, got %d, expected %d", + ntohl(th->th_ack), seq); + + ack++; + t_state = T_CLOSING; + + reply = prepare_ack_packet(af, htons(MY_PORT), htons(PEER_PORT)); + seq++; + break; + case T_CLOSING: + zassert_true(false, "Should not receive anything after final ACK"); + break; + default: + zassert_true(false, "%s unexpected state", __func__); + return; + } + + if (reply != NULL) { + zassert_ok(net_recv_data(net_iface, reply), "%s failed", __func__); + } +} + +/* Receive callback to be installed in the accept handler */ +static void test_fin_ack_after_data_recv_cb(struct net_context *context, + struct net_pkt *pkt, + union net_ip_header *ip_hdr, + union net_proto_header *proto_hdr, + int status, + void *user_data) +{ + zassert_ok(status, "failed to recv the data"); + + if (pkt != NULL) { + uint8_t buf[sizeof(TEST_FIN_ACK_AFTER_DATA_REQ)] = { 0 }; + int data_len = net_pkt_remaining_data(pkt); + + zassert_equal(data_len, sizeof(TEST_FIN_ACK_AFTER_DATA_REQ) - 1, + "Invalid packet length, %d", data_len); + zassert_ok(net_pkt_read(pkt, buf, data_len)); + zassert_mem_equal(buf, TEST_FIN_ACK_AFTER_DATA_REQ, data_len); + + net_pkt_unref(pkt); + } + + test_sem_give(); +} + +static void test_fin_ack_after_data_accept_cb(struct net_context *ctx, + struct sockaddr *addr, + socklen_t addrlen, + int status, + void *user_data) +{ + int ret; + + zassert_ok(status, "failed to accept the conn"); + + /* set callback on newly created context */ + accepted_ctx = ctx; + ret = net_context_recv(ctx, test_fin_ack_after_data_recv_cb, + K_NO_WAIT, NULL); + zassert_ok(ret, "Failed to recv data from peer"); + + /* Ref the context on the app behalf. */ + net_context_ref(ctx); +} + +/* Verify that the TCP stack replies with a valid FIN,ACK after the peer + * acknowledges the latest data in the FIN packet. + * Test case scenario IPv4 + * send SYN, + * expect SYN ACK, + * send ACK with Data, + * expect ACK, + * expect Data, + * send FIN,ACK + * expect FIN,ACK + * send ACK + * any failures cause test case to fail. + */ +ZTEST(net_tcp, test_server_fin_ack_after_data) +{ + struct net_context *ctx; + int ret; + + test_case_no = TEST_SERVER_FIN_ACK_AFTER_DATA; + + t_state = T_SYN; + seq = ack = 0; + + ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ctx); + zassert_ok(ret, "Failed to get net_context"); + + net_context_ref(ctx); + + ret = net_context_bind(ctx, (struct sockaddr *)&my_addr_s, + sizeof(struct sockaddr_in)); + zassert_ok(ret, "Failed to bind net_context"); + + /* Put context into listening mode and install accept cb */ + ret = net_context_listen(ctx, 1); + zassert_ok(ret, "Failed to listen on net_context"); + + ret = net_context_accept(ctx, test_fin_ack_after_data_accept_cb, + K_NO_WAIT, NULL); + zassert_ok(ret, "Failed to set accept on net_context"); + + /* Trigger the peer to send SYN */ + handle_server_fin_ack_after_data_test(AF_INET, NULL); + + /* test_fin_ack_after_data_recv_cb will release the semaphore after + * dummy request is read. + */ + test_sem_take(K_MSEC(100), __LINE__); + + /* Send dummy "response" */ + ret = net_context_send(accepted_ctx, TEST_FIN_ACK_AFTER_DATA_RSP, + sizeof(TEST_FIN_ACK_AFTER_DATA_RSP) - 1, NULL, + K_NO_WAIT, NULL); + zassert_equal(ret, sizeof(TEST_FIN_ACK_AFTER_DATA_RSP) - 1, + "Failed to send data to peer %d", ret); + + /* test_fin_ack_after_data_recv_cb will release the semaphore after + * the connection is marked closed. + */ + test_sem_take(K_MSEC(100), __LINE__); + + net_context_put(ctx); + net_context_put(accepted_ctx); + + /* Connection is in TIME_WAIT state, context will be released + * after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it. + */ + k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY)); +} + ZTEST_SUITE(net_tcp, NULL, presetup, NULL, NULL, NULL); diff --git a/tests/subsys/dfu/img_util/src/main.c b/tests/subsys/dfu/img_util/src/main.c index dc7c46721267..33956be6251e 100644 --- a/tests/subsys/dfu/img_util/src/main.c +++ b/tests/subsys/dfu/img_util/src/main.c @@ -12,8 +12,9 @@ #define SLOT0_PARTITION slot0_partition #define SLOT1_PARTITION slot1_partition -#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ - (FIXED_PARTITION_OFFSET(label) == CONFIG_FLASH_LOAD_OFFSET) +#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ + (FIXED_PARTITION_OFFSET(label) <= CONFIG_FLASH_LOAD_OFFSET && \ + FIXED_PARTITION_OFFSET(label) + FIXED_PARTITION_SIZE(label) > CONFIG_FLASH_LOAD_OFFSET) #if FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot0_partition) #define UPLOAD_PARTITION_ID FIXED_PARTITION_ID(SLOT1_PARTITION) diff --git a/tests/subsys/fs/fcb/sysbuild.conf b/tests/subsys/fs/fcb/sysbuild.conf new file mode 100644 index 000000000000..6408669a8474 --- /dev/null +++ b/tests/subsys/fs/fcb/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/subsys/fs/littlefs/sysbuild.conf b/tests/subsys/fs/littlefs/sysbuild.conf new file mode 100644 index 000000000000..6408669a8474 --- /dev/null +++ b/tests/subsys/fs/littlefs/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/subsys/fs/zms/src/main.c b/tests/subsys/fs/zms/src/main.c index a69a2b009537..80e2d9f9c072 100644 --- a/tests/subsys/fs/zms/src/main.c +++ b/tests/subsys/fs/zms/src/main.c @@ -578,17 +578,19 @@ ZTEST_F(zms, test_zms_gc_corrupt_close_ate) int err; Z_TEST_SKIP_IFNDEF(CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES); - close_ate.id = 0xffffffff; + memset(&close_ate, 0xff, sizeof(struct zms_ate)); + close_ate.id = ZMS_HEAD_ID; close_ate.offset = fixture->fs.sector_size - sizeof(struct zms_ate) * 5; close_ate.len = 0; - close_ate.metadata = 0xffffffff; close_ate.cycle_cnt = 1; close_ate.crc8 = 0xff; /* Incorrect crc8 */ - empty_ate.id = 0xffffffff; - empty_ate.offset = 0; + memset(&empty_ate, 0, sizeof(struct zms_ate)); + empty_ate.id = ZMS_HEAD_ID; empty_ate.len = 0xffff; - empty_ate.metadata = 0x4201; + empty_ate.metadata = FIELD_PREP(ZMS_VERSION_MASK, ZMS_DEFAULT_VERSION) | + FIELD_PREP(ZMS_MAGIC_NUMBER_MASK, ZMS_MAGIC_NUMBER) | + FIELD_PREP(ZMS_ATE_FORMAT_MASK, ZMS_DEFAULT_ATE_FORMAT); empty_ate.cycle_cnt = 1; empty_ate.crc8 = crc8_ccitt(0xff, (uint8_t *)&empty_ate + SIZEOF_FIELD(struct zms_ate, crc8), @@ -649,7 +651,7 @@ ZTEST_F(zms, test_zms_gc_corrupt_ate) struct zms_ate close_ate; int err; - close_ate.id = 0xffffffff; + close_ate.id = ZMS_HEAD_ID; close_ate.offset = fixture->fs.sector_size / 2; close_ate.len = 0; close_ate.crc8 = @@ -752,6 +754,8 @@ ZTEST_F(zms, test_zms_cache_init) num = num_matching_cache_entries(ate_addr, false, &fixture->fs); zassert_equal(num, 1, "invalid cache entry after restart"); +#else + ztest_test_skip(); #endif } @@ -780,6 +784,8 @@ ZTEST_F(zms, test_zms_cache_collission) zassert_equal(err, sizeof(data), "zms_read call failure: %d", err); zassert_equal(data, id, "incorrect data read"); } +#else + ztest_test_skip(); #endif } @@ -829,6 +835,8 @@ ZTEST_F(zms, test_zms_cache_gc) num = num_matching_cache_entries(2ULL << ADDR_SECT_SHIFT, true, &fixture->fs); zassert_equal(num, 2, "invalid cache content after gc"); +#else + ztest_test_skip(); #endif } @@ -886,7 +894,8 @@ ZTEST_F(zms, test_zms_cache_hash_quality) TC_PRINT("Cache occupancy: %u\n", (unsigned int)num); zassert_between_inclusive(num, MIN_CACHE_OCCUPANCY, CONFIG_ZMS_LOOKUP_CACHE_SIZE, "too low cache occupancy - poor hash quality"); - +#else + ztest_test_skip(); #endif } @@ -948,3 +957,45 @@ ZTEST_F(zms, test_zms_input_validation) err = zms_delete(&fixture->fs, 0); zassert_true(err == -EACCES, "zms_delete call before mount fs failure: %d", err); } + +/* + * Test 64 bit ZMS ID support. + */ +ZTEST_F(zms, test_zms_id_64bit) +{ + int err; + ssize_t len; + uint64_t data; + uint64_t filling_id = 0xdeadbeefULL; + + Z_TEST_SKIP_IFNDEF(CONFIG_ZMS_ID_64BIT); + + err = zms_mount(&fixture->fs); + zassert_true(err == 0, "zms_mount call failure: %d", err); + + /* Fill the first sector with writes of different IDs */ + + while (fixture->fs.data_wra + sizeof(data) + sizeof(struct zms_ate) <= + fixture->fs.ate_wra) { + data = filling_id; + len = zms_write(&fixture->fs, (zms_id_t)filling_id, &data, sizeof(data)); + zassert_true(len == sizeof(data), "zms_write failed: %d", len); + + /* Choose the next ID so that its lower 32 bits stay invariant. + * The purpose is to test that ZMS doesn't mistakenly cast the + * 64 bit ID to a 32 bit one somewhere. + */ + filling_id += BIT64(32); + } + + /* Read back the written entries and check that they're all unique */ + + for (uint64_t id = 0xdeadbeefULL; id < filling_id; id += BIT64(32)) { + len = zms_read_hist(&fixture->fs, (zms_id_t)id, &data, sizeof(data), 0); + zassert_true(len == sizeof(data), "zms_read_hist unexpected failure: %d", len); + zassert_equal(data, id, "read unexpected data: %llx instead of %llx", data, id); + + len = zms_read_hist(&fixture->fs, (zms_id_t)id, &data, sizeof(data), 1); + zassert_true(len == -ENOENT, "zms_read_hist unexpected failure: %d", len); + } +} diff --git a/tests/subsys/fs/zms/testcase.yaml b/tests/subsys/fs/zms/testcase.yaml index bdee4529f2af..14cb7e9c36a2 100644 --- a/tests/subsys/fs/zms/testcase.yaml +++ b/tests/subsys/fs/zms/testcase.yaml @@ -8,21 +8,28 @@ tests: extra_args: DTC_OVERLAY_FILE=boards/qemu_x86_ev_0x00.overlay platform_allow: qemu_x86 filesystem.zms.sim.no_erase: - extra_args: CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + extra_configs: + - CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n platform_allow: qemu_x86 filesystem.zms.sim.corrupt_close: - extra_args: + extra_configs: - CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=y - CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y platform_allow: qemu_x86 filesystem.zms.cache: - extra_args: + extra_configs: - CONFIG_ZMS_LOOKUP_CACHE=y - CONFIG_ZMS_LOOKUP_CACHE_SIZE=64 platform_allow: native_sim filesystem.zms.data_crc: - extra_args: + extra_configs: - CONFIG_ZMS_DATA_CRC=y platform_allow: - native_sim - qemu_x86 + filesystem.zms.id_64bit: + extra_configs: + - CONFIG_ZMS_ID_64BIT=y + - CONFIG_ZMS_LOOKUP_CACHE=y + - CONFIG_ZMS_LOOKUP_CACHE_SIZE=64 + platform_allow: qemu_x86 diff --git a/tests/subsys/modem/mock/modem_backend_mock.c b/tests/subsys/modem/mock/modem_backend_mock.c index 5b7b47c0eb49..49ea1927076b 100644 --- a/tests/subsys/modem/mock/modem_backend_mock.c +++ b/tests/subsys/modem/mock/modem_backend_mock.c @@ -52,12 +52,15 @@ static int modem_backend_mock_transmit(void *data, const uint8_t *buf, size_t si return ret; } - ret = ring_buf_put(&mock->tx_rb, buf, size); if (modem_backend_mock_update(mock, buf, size)) { + /* Skip ringbuffer if transaction consumes bytes */ + ret = size; modem_backend_mock_put(mock, mock->transaction->put, mock->transaction->put_size); - mock->transaction = NULL; + modem_backend_mock_prime(mock, mock->transaction->next); + } else { + ret = ring_buf_put(&mock->tx_rb, buf, size); } k_work_submit(&mock->transmit_idle_work); @@ -137,6 +140,10 @@ int modem_backend_mock_get(struct modem_backend_mock *mock, uint8_t *buf, size_t void modem_backend_mock_put(struct modem_backend_mock *mock, const uint8_t *buf, size_t size) { + if (size == 0) { + return; + } + __ASSERT(ring_buf_put(&mock->rx_rb, buf, size) == size, "Mock buffer capacity exceeded"); @@ -155,3 +162,10 @@ void modem_backend_mock_bridge(struct modem_backend_mock *mock_a, struct modem_b mock_a->bridge = mock_b; mock_b->bridge = mock_a; } + +void modem_backend_mock_wait_for_transaction(struct modem_backend_mock *mock) +{ + while (mock->transaction) { + k_msleep(1); + } +} diff --git a/tests/subsys/modem/mock/modem_backend_mock.h b/tests/subsys/modem/mock/modem_backend_mock.h index 56a5b585cb12..34b79aca552f 100644 --- a/tests/subsys/modem/mock/modem_backend_mock.h +++ b/tests/subsys/modem/mock/modem_backend_mock.h @@ -19,6 +19,9 @@ struct modem_backend_mock_transaction { /* Data which will be put in response to get data */ const uint8_t *put; size_t put_size; + + /* Next transaction in chain */ + const struct modem_backend_mock_transaction *next; }; struct modem_backend_mock { @@ -62,4 +65,6 @@ void modem_backend_mock_prime(struct modem_backend_mock *mock, void modem_backend_mock_bridge(struct modem_backend_mock *mock_a, struct modem_backend_mock *mock_b); +void modem_backend_mock_wait_for_transaction(struct modem_backend_mock *mock); + #endif /* ZEPHYR_DRIVERS_MODEM_MODEM_PIPE_MOCK */ diff --git a/tests/subsys/modem/modem_cmux/src/main.c b/tests/subsys/modem/modem_cmux/src/main.c index b1adce37cc46..b40af7e0de89 100644 --- a/tests/subsys/modem/modem_cmux/src/main.c +++ b/tests/subsys/modem/modem_cmux/src/main.c @@ -117,17 +117,19 @@ static uint8_t cmux_frame_control_cld_ack[] = {0xF9, 0x03, 0xEF, 0x05, 0xC1, 0x0 static uint8_t cmux_frame_dlci1_sabm_cmd[] = {0xF9, 0x07, 0x3F, 0x01, 0xDE, 0xF9}; static uint8_t cmux_frame_dlci1_sabm_ack[] = {0xF9, 0x07, 0x73, 0x01, 0x15, 0xF9}; static uint8_t cmux_frame_dlci1_disc_cmd[] = {0xF9, 0x07, 0x53, 0x01, 0x3F, 0xF9}; +static uint8_t cmux_frame_dlci1_msc_cmd[] = {0xF9, 0x03, 0xEF, 0x09, 0xE3, + 0x05, 0x07, 0x8D, 0xFB, 0xF9}; static uint8_t cmux_frame_dlci1_ua_ack[] = {0xF9, 0x07, 0x73, 0x01, 0x15, 0xF9}; static uint8_t cmux_frame_dlci2_sabm_cmd[] = {0xF9, 0x0B, 0x3F, 0x01, 0x59, 0xF9}; static uint8_t cmux_frame_dlci2_sabm_ack[] = {0xF9, 0x0B, 0x73, 0x01, 0x92, 0xF9}; static uint8_t cmux_frame_dlci2_disc_cmd[] = {0xF9, 0x0B, 0x53, 0x01, 0xB8, 0xF9}; +static uint8_t cmux_frame_dlci2_msc_cmd[] = {0xF9, 0x03, 0xEF, 0x09, 0xE3, + 0x05, 0x0B, 0x8D, 0xFB, 0xF9}; static uint8_t cmux_frame_dlci2_ua_ack[] = {0xF9, 0x0B, 0x73, 0x01, 0x92, 0xF9}; -static uint8_t cmux_frame_control_msc_cmd[] = {0xF9, 0x01, 0xFF, 0x0B, 0xE3, - 0x07, 0x0B, 0x09, 0x01, 0x6C, 0xF9}; - -static uint8_t cmux_frame_control_msc_ack[] = {0xF9, 0x01, 0xFF, 0x0B, 0xE1, - 0x07, 0x0B, 0x09, 0x01, 0x6C, 0xF9}; - +static uint8_t cmux_frame_control_msc_cmd[] = {0xF9, 0x01, 0xEF, 0x09, 0xE3, + 0x05, 0x07, 0x01, 0x9A, 0xF9}; +static uint8_t cmux_frame_control_msc_ack[] = {0xF9, 0x01, 0xEF, 0x09, 0xE1, + 0x05, 0x07, 0x01, 0x9A, 0xF9}; static uint8_t cmux_frame_control_fcon_cmd[] = {0xF9, 0x01, 0xFF, 0x05, 0xA3, 0x01, 0x86, 0xF9}; static uint8_t cmux_frame_control_fcon_ack[] = {0xF9, 0x01, 0xFF, 0x05, 0xA1, 0x01, 0x86, 0xF9}; static uint8_t cmux_frame_control_fcoff_cmd[] = {0xF9, 0x01, 0xFF, 0x05, 0x63, 0x01, 0x86, 0xF9}; @@ -227,19 +229,31 @@ const static struct modem_backend_mock_transaction transaction_dlci2_disc = { .put_size = sizeof(cmux_frame_dlci2_ua_ack) }; +const static struct modem_backend_mock_transaction transaction_dlci1_msc = { + .get = cmux_frame_dlci1_msc_cmd, + .get_size = sizeof(cmux_frame_dlci1_msc_cmd), + .put = NULL, + .put_size = 0}; + +const static struct modem_backend_mock_transaction transaction_dlci2_msc = { + .get = cmux_frame_dlci2_msc_cmd, + .get_size = sizeof(cmux_frame_dlci2_msc_cmd), + .put = NULL, + .put_size = 0}; + const static struct modem_backend_mock_transaction transaction_dlci1_sabm = { .get = cmux_frame_dlci1_sabm_cmd, .get_size = sizeof(cmux_frame_dlci1_sabm_cmd), .put = cmux_frame_dlci1_ua_ack, - .put_size = sizeof(cmux_frame_dlci1_ua_ack) -}; + .put_size = sizeof(cmux_frame_dlci1_ua_ack), + .next = &transaction_dlci1_msc}; const static struct modem_backend_mock_transaction transaction_dlci2_sabm = { .get = cmux_frame_dlci2_sabm_cmd, .get_size = sizeof(cmux_frame_dlci2_sabm_cmd), .put = cmux_frame_dlci2_ua_ack, - .put_size = sizeof(cmux_frame_dlci2_ua_ack) -}; + .put_size = sizeof(cmux_frame_dlci2_ua_ack), + .next = &transaction_dlci2_msc}; static void test_modem_cmux_callback(struct modem_cmux *cmux, enum modem_cmux_event event, void *user_data) @@ -317,6 +331,9 @@ static void *test_modem_cmux_setup(void) events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI2_OPEN, false, K_MSEC(100)); __ASSERT_NO_MSG((events & EVENT_CMUX_DLCI2_OPEN)); + /* Consume the MSC command sent after DLCI opening */ + modem_backend_mock_wait_for_transaction(&bus_mock); + return NULL; } @@ -603,8 +620,8 @@ ZTEST(modem_cmux, test_modem_cmux_dlci1_close_open) zassert_true((events & EVENT_CMUX_DLCI1_OPEN), "DLCI1 not opened as expected"); - /* Wait for potential T1 timeout */ - k_msleep(500); + modem_backend_mock_prime(&bus_mock, &transaction_dlci1_msc); + modem_backend_mock_wait_for_transaction(&bus_mock); ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1)); zassert_true(ret == 0, "Received unexpected data"); @@ -705,6 +722,9 @@ ZTEST(modem_cmux, test_modem_cmux_disconnect_connect) zassert_true((events & EVENT_CMUX_DLCI1_OPEN), "DLCI1 not opened as expected"); + modem_backend_mock_prime(&bus_mock, &transaction_dlci1_msc); + modem_backend_mock_wait_for_transaction(&bus_mock); + /* Wait for potential T1 timeout */ k_msleep(500); @@ -730,8 +750,10 @@ ZTEST(modem_cmux, test_modem_cmux_disconnect_connect) events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI2_OPEN), false, K_MSEC(100)); - zassert_true((events & EVENT_CMUX_DLCI2_OPEN), - "DLCI1 not opened as expected"); + zassert_true((events & EVENT_CMUX_DLCI2_OPEN), "DLCI2 not opened as expected"); + + modem_backend_mock_prime(&bus_mock, &transaction_dlci2_msc); + modem_backend_mock_wait_for_transaction(&bus_mock); /* Wait for potential T1 timeout */ k_msleep(500); @@ -746,6 +768,10 @@ ZTEST(modem_cmux, test_modem_cmux_disconnect_connect_sync) zassert_true(modem_pipe_close(dlci1_pipe, K_SECONDS(10)) == 0, "Failed to close DLCI1"); modem_backend_mock_prime(&bus_mock, &transaction_dlci2_disc); zassert_true(modem_pipe_close(dlci2_pipe, K_SECONDS(10)) == 0, "Failed to close DLCI2"); + + /* Clear any pending data before CLD transaction */ + modem_backend_mock_reset(&bus_mock); + modem_backend_mock_prime(&bus_mock, &transaction_control_cld); zassert_true(modem_cmux_disconnect(&cmux) == 0, "Failed to disconnect CMUX"); zassert_true(modem_cmux_disconnect(&cmux) == -EALREADY, @@ -759,9 +785,11 @@ ZTEST(modem_cmux, test_modem_cmux_disconnect_connect_sync) modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm); zassert_true(modem_pipe_open(dlci1_pipe, K_SECONDS(10)) == 0, "Failed to open DLCI1 pipe"); + modem_backend_mock_wait_for_transaction(&bus_mock); modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm); zassert_true(modem_pipe_open(dlci2_pipe, K_SECONDS(10)) == 0, "Failed to open DLCI2 pipe"); + modem_backend_mock_wait_for_transaction(&bus_mock); } ZTEST(modem_cmux, test_modem_cmux_dlci_close_open_sync) @@ -773,9 +801,11 @@ ZTEST(modem_cmux, test_modem_cmux_dlci_close_open_sync) modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm); zassert_true(modem_pipe_open(dlci1_pipe, K_SECONDS(10)) == 0, "Failed to open DLCI1 pipe"); + modem_backend_mock_wait_for_transaction(&bus_mock); modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm); zassert_true(modem_pipe_open(dlci2_pipe, K_SECONDS(10)) == 0, "Failed to open DLCI2 pipe"); + modem_backend_mock_wait_for_transaction(&bus_mock); } ZTEST(modem_cmux, test_modem_cmux_prevent_work_while_released) @@ -820,10 +850,13 @@ ZTEST(modem_cmux, test_modem_cmux_prevent_work_while_released) zassert_ok(modem_cmux_attach(&cmux, bus_mock_pipe)); modem_backend_mock_prime(&bus_mock, &transaction_control_sabm); zassert_ok(modem_cmux_connect(&cmux)); + modem_backend_mock_wait_for_transaction(&bus_mock); modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm); zassert_ok(modem_pipe_open(dlci1_pipe, K_SECONDS(10))); + modem_backend_mock_wait_for_transaction(&bus_mock); modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm); zassert_ok(modem_pipe_open(dlci2_pipe, K_SECONDS(10))); + modem_backend_mock_wait_for_transaction(&bus_mock); } ZTEST(modem_cmux, test_modem_drop_frames_with_invalid_length) @@ -886,4 +919,41 @@ ZTEST(modem_cmux, test_modem_cmux_split_large_data) "Incorrect number of bytes transmitted %d", ret); } +ZTEST(modem_cmux, test_modem_cmux_invalid_cr) +{ + uint32_t events; + + /* We are initiator, so any CMD with CR set should be dropped */ + modem_backend_mock_put(&bus_mock, cmux_frame_control_cld_cmd, + sizeof(cmux_frame_control_cld_cmd)); + + modem_backend_mock_put(&bus_mock, cmux_frame_control_sabm_cmd, + sizeof(cmux_frame_control_sabm_cmd)); + + events = k_event_wait_all(&cmux_event, + (MODEM_CMUX_EVENT_CONNECTED | MODEM_CMUX_EVENT_DISCONNECTED), + false, K_MSEC(100)); + + zassert_false(events, "Wrong CMD should have been ignored"); +} + +ZTEST(modem_cmux, test_modem_cmux_invalid_command) +{ + static uint8_t invalid_cmd[] = {0xF9, 0x03, 0xEF, 0x09, 0x00, + 0x00, 0x00, 0x00, 0xFB, 0xF9}; + uint32_t events; + + modem_backend_mock_put(&bus_mock, invalid_cmd, + sizeof(invalid_cmd)); + + events = k_event_wait_all(&cmux_event, + (MODEM_CMUX_EVENT_CONNECTED | MODEM_CMUX_EVENT_DISCONNECTED), + false, K_SECONDS(1)); + + zassert_false(events, "Wrong CMD should have been ignored"); + + /* Invalid command should not cause any response */ + zassert_equal(0, modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1))); +} + ZTEST_SUITE(modem_cmux, NULL, test_modem_cmux_setup, test_modem_cmux_before, NULL, NULL); diff --git a/tests/subsys/modem/modem_cmux_pair/src/main.c b/tests/subsys/modem/modem_cmux_pair/src/main.c index 5cc8fed4b458..1988e9d73319 100644 --- a/tests/subsys/modem/modem_cmux_pair/src/main.c +++ b/tests/subsys/modem/modem_cmux_pair/src/main.c @@ -507,9 +507,10 @@ ZTEST(modem_cmux_pair, test_modem_cmux_disconnect_connect) modem_backend_mock_reset(&bus_mock_dte); zassert_true(modem_cmux_disconnect_async(&cmux_dte) == 0, "Failed to disconnect CMUX"); - k_msleep(100); + events = k_event_wait_all(&cmux_event_dte, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(660)); + zassert_true((events & EVENT_CMUX_DISCONNECTED), "Failed to disconnect CMUX"); - events = k_event_wait_all(&cmux_event_dte, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(100)); + events = k_event_wait_all(&cmux_event_dce, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(660)); zassert_true((events & EVENT_CMUX_DISCONNECTED), "Failed to disconnect CMUX"); /* Reconnect CMUX */ @@ -554,6 +555,9 @@ ZTEST(modem_cmux_pair, test_modem_cmux_disconnect_connect_sync) zassert_true(modem_cmux_disconnect(&cmux_dte) == 0, "Failed to disconnect CMUX"); zassert_true(modem_cmux_disconnect(&cmux_dte) == -EALREADY, "Should already be disconnected"); + + events = k_event_wait_all(&cmux_event_dce, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(660)); + zassert_true((events & EVENT_CMUX_DISCONNECTED), "Failed to disconnect CMUX"); zassert_true(modem_cmux_disconnect(&cmux_dce) == -EALREADY, "Should already be disconnected"); diff --git a/tests/subsys/modem/modem_pipe/src/main.c b/tests/subsys/modem/modem_pipe/src/main.c index 3cb330550fd5..7889d111d1b9 100644 --- a/tests/subsys/modem/modem_pipe/src/main.c +++ b/tests/subsys/modem/modem_pipe/src/main.c @@ -327,6 +327,14 @@ static void test_pipe_notify_receive_ready(void) "Unexpected state %u", (uint32_t)atomic_get(&test_state)); } +static void test_pipe_receive_closed(void) +{ + /* Try to receive from a closed pipe - should return 0 */ + zassert_equal(modem_pipe_receive(test_pipe, test_buffer, test_buffer_size), 0, + "Reading from closed pipe should return 0"); + zassert_false(test_backend.receive_called, "receive should not be called on closed pipe"); +} + ZTEST(modem_pipe, test_async_open_close) { test_pipe_open(); @@ -397,5 +405,16 @@ ZTEST(modem_pipe, test_attach) test_pipe_attach_receive_not_ready_transmit_idle(); } +ZTEST(modem_pipe, test_receive_closed) +{ + test_pipe_open(); + test_reset(); + test_pipe_async_transmit(); + test_reset(); + test_pipe_close(); + /* Test reading from a closed pipe should return 0 */ + test_pipe_receive_closed(); +} + ZTEST_SUITE(modem_pipe, NULL, modem_backend_fake_setup, modem_backend_fake_before, modem_backend_fake_after, NULL); diff --git a/tests/subsys/secure_storage/psa/crypto/testcase.yaml b/tests/subsys/secure_storage/psa/crypto/testcase.yaml index 1482d23cb6c7..150177b8e3fc 100644 --- a/tests/subsys/secure_storage/psa/crypto/testcase.yaml +++ b/tests/subsys/secure_storage/psa/crypto/testcase.yaml @@ -1,6 +1,9 @@ common: tags: - psa.secure_storage + platform_exclude: + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad tests: secure_storage.psa.crypto.secure_storage: filter: CONFIG_SECURE_STORAGE and not CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_NONE diff --git a/tests/subsys/secure_storage/psa/its/testcase.yaml b/tests/subsys/secure_storage/psa/its/testcase.yaml index 75950a798143..c794ea1797e5 100644 --- a/tests/subsys/secure_storage/psa/its/testcase.yaml +++ b/tests/subsys/secure_storage/psa/its/testcase.yaml @@ -4,6 +4,8 @@ common: - nrf54l15dk/nrf54l15/cpuapp platform_exclude: - qemu_cortex_m0 # settings subsystem initialization fails + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad timeout: 600 tags: - psa.secure_storage @@ -27,6 +29,7 @@ tests: - EXTRA_DTC_OVERLAY_FILE=zms.overlay - EXTRA_CONF_FILE=\ overlay-secure_storage.conf;overlay-store_zms.conf;overlay-transform_default.conf + - SB_CONFIG_PARTITION_MANAGER=n secure_storage.psa.its.secure_storage.store.zms.64-bit_uids: platform_allow: *zms_platform_allow diff --git a/tests/subsys/settings/its/testcase.yaml b/tests/subsys/settings/its/testcase.yaml index de11f1ef7264..c63019e63457 100644 --- a/tests/subsys/settings/its/testcase.yaml +++ b/tests/subsys/settings/its/testcase.yaml @@ -10,5 +10,6 @@ tests: - max32657evkit/max32657/ns - nrf5340dk/nrf5340/cpuapp/ns - nrf54l15dk/nrf54l15/cpuapp/ns + - nrf54lm20dk/nrf54lm20a/cpuapp/ns platform_exclude: - lpcxpresso55s69/lpc55s69/cpu0/ns diff --git a/west.yml b/west.yml index bcef02412e50..1bff38e1c7b8 100644 --- a/west.yml +++ b/west.yml @@ -200,7 +200,7 @@ manifest: groups: - hal - name: hal_nordic - revision: 54f33f10a0b826174fb145f155afa61ce5a44b93 + revision: 7858281d843468fe53c829995fb63f45a227387a path: modules/hal/nordic groups: - hal @@ -226,7 +226,7 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: 74c9186c0a01c53e320421bd0e8b85fc266f3260 + revision: 740a944351300664ea17fb7913f0036a5263f008 groups: - hal - name: hal_rpi_pico @@ -337,7 +337,7 @@ manifest: revision: 40403f5f2805cca210d2a47c8717d89c4e816cda path: modules/bsim_hw_models/nrf_hw_models - name: nrf_wifi - revision: 5fffeab6496932abb10f9dae53ed3686967aa050 + revision: e269670cd17fb8ccc4b7004544276bc7d9578496 path: modules/lib/nrf_wifi - name: open-amp revision: c30a6d8b92fcebdb797fc1a7698e8729e250f637