diff --git a/.github/workflows/bsim-tests.yaml b/.github/workflows/bsim-tests.yaml index e4f76dec506bf1f..75a65577975c967 100644 --- a/.github/workflows/bsim-tests.yaml +++ b/.github/workflows/bsim-tests.yaml @@ -80,7 +80,7 @@ jobs: west forall -c 'git reset --hard HEAD' - name: Check common triggering files - uses: tj-actions/changed-files@v35 + uses: tj-actions/changed-files@v41 id: check-common-files with: files: | @@ -95,7 +95,7 @@ jobs: tests/bsim/* - name: Check if Bluethooth files changed - uses: tj-actions/changed-files@v35 + uses: tj-actions/changed-files@v41 id: check-bluetooth-files with: files: | @@ -104,7 +104,7 @@ jobs: subsys/bluetooth/** - name: Check if Networking files changed - uses: tj-actions/changed-files@v35 + uses: tj-actions/changed-files@v41 id: check-networking-files with: files: | diff --git a/.github/workflows/do_not_merge.yml b/.github/workflows/do_not_merge.yml index 14c651a25f1e003..b6954e288c92269 100644 --- a/.github/workflows/do_not_merge.yml +++ b/.github/workflows/do_not_merge.yml @@ -7,12 +7,14 @@ on: jobs: do-not-merge: if: ${{ contains(github.event.*.labels.*.name, 'DNM') || - contains(github.event.*.labels.*.name, 'TSC') }} + contains(github.event.*.labels.*.name, 'TSC') || + contains(github.event.*.labels.*.name, 'Architecture Review') || + contains(github.event.*.labels.*.name, 'dev-review') }} name: Prevent Merging runs-on: ubuntu-22.04 steps: - name: Check for label run: | - echo "Pull request is labeled as 'DNM' or 'TSC'" - echo "This workflow fails so that the pull request cannot be merged" + echo "Pull request is labeled as 'DNM', 'TSC', 'Architecture Review' or 'dev-review'." + echo "This workflow fails so that the pull request cannot be merged." exit 1 diff --git a/.github/workflows/twister.yaml b/.github/workflows/twister.yaml index 49a30e09cdab366..983a97f8973eef0 100644 --- a/.github/workflows/twister.yaml +++ b/.github/workflows/twister.yaml @@ -179,6 +179,12 @@ jobs: west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /github/cache/zephyrproject) west forall -c 'git reset --hard HEAD' + # Hotfix until we have kitware ninja in the docker image. + # Needed for full functionality of the job server functionality in twister which only works with + # kitware supplied ninja version. + wget -c https://github.com/Kitware/ninja/releases/download/v1.11.1.g95dee.kitware.jobserver-1/ninja-1.11.1.g95dee.kitware.jobserver-1_x86_64-linux-gnu.tar.gz -O - | tar xz --strip-components=1 + sudo cp ninja /usr/local/bin + - name: Check Environment run: | cmake --version diff --git a/CMakeLists.txt b/CMakeLists.txt index be0dafe0fc12a9f..e3e65cf26eb26f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1622,18 +1622,20 @@ if(CONFIG_BUILD_OUTPUT_BIN AND CONFIG_BUILD_OUTPUT_UF2) endif() if(CONFIG_BUILD_OUTPUT_META) + set(KERNEL_META_PATH ${PROJECT_BINARY_DIR}/${KERNEL_META_NAME} CACHE INTERNAL "") + list(APPEND post_build_commands COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/zephyr_module.py ${WEST_ARG} ${ZEPHYR_MODULES_ARG} ${EXTRA_ZEPHYR_MODULES_ARG} - --meta-out ${KERNEL_META_NAME} + --meta-out ${KERNEL_META_PATH} $<$:--meta-state-propagate> ) list(APPEND post_build_byproducts - ${KERNEL_META_NAME} + ${KERNEL_META_PATH} ) endif() diff --git a/CODEOWNERS b/CODEOWNERS index 8c2b478fb4a7279..af2cb6c5d51fdea 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -133,6 +133,7 @@ /boards/shields/inventek_eswifi/ @nandojve /boards/xtensa/odroid_go/ @ydamigos /boards/xtensa/nxp_adsp_imx8/ @iuliana-prodan @dbaluta +/boards/xtensa/kincony_kc868_a32/ @bbilas /boards/arm64/qemu_cortex_a53/ @carlocaione /boards/arm64/bcm958402m2_a72/ @abhishek-brcm /boards/arm64/mimx8mm_evk/ @MrVan @JiafeiPan diff --git a/Kconfig.zephyr b/Kconfig.zephyr index 8b48eca6fcd96c3..c384c8053f9fb54 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -872,7 +872,7 @@ config IS_BOOTLOADER a separate Zephyr image payload. config BOOTLOADER_SRAM_SIZE - int "SRAM reserved for bootloader" + int "SRAM reserved for bootloader [DEPRECATED]" default 0 depends on !XIP || IS_BOOTLOADER depends on ARM || XTENSA @@ -883,6 +883,20 @@ config BOOTLOADER_SRAM_SIZE - Zephyr is a !XIP image, which implicitly assumes existence of a bootloader that loads the Zephyr !XIP image onto SRAM. + This option is deprecated, users should transition to using DTS to set this, if needed. + To be removed after Zephyr 3.7 release. + +config BOOTLOADER_SRAM_SIZE_DEPRECATED + bool + default y + select DEPRECATED + depends on BOOTLOADER_SRAM_SIZE != 0 + depends on !XIP || IS_BOOTLOADER + depends on ARM || XTENSA + help + Non-prompt symbol to indicate that the deprecated BOOTLOADER_SRAM_SIZE Kconfig has a + non-0 value. Please transition to using devicetree. + config BOOTLOADER_ESP_IDF bool "ESP-IDF bootloader support" depends on SOC_FAMILY_ESP32 && !BOOTLOADER_MCUBOOT && !MCUBOOT diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 8b1a9075d4ac60e..9cee672506f9085 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -252,8 +252,10 @@ Ambiq Platforms: - soc/arm/ambiq/ - boards/arm/apollo*/ - dts/arm/ambiq/ - - dts/bindings/*/ambiq* - - drivers/*/*_ambiq* + - dts/bindings/*/ambiq,* + - drivers/*/*ambiq* + - drivers/*/*/*ambiq* + - drivers/*/*/*apollo* labels: - "platform: Ambiq" @@ -351,17 +353,14 @@ Bluetooth controller: Bluetooth Host: status: maintained maintainers: + - jori-nordic - jhedberg collaborators: - hermabe - - jori-nordic - alwa-nordic - - Vudentz - Thalley - - asbjornsabo - sjanc - theob-pro - - kruithofa files: - drivers/bluetooth/ - subsys/bluetooth/host/ @@ -383,6 +382,7 @@ Bluetooth Mesh: - alxelax - Andrewpini - akredalen + - HaavardRei files: - subsys/bluetooth/mesh/ - include/zephyr/bluetooth/mesh/ @@ -2728,6 +2728,8 @@ POSIX API layer: status: maintained maintainers: - cfriedt + collaborators: + - ycsin files: - include/zephyr/posix/ - lib/posix/ @@ -2995,7 +2997,7 @@ GD32 Platforms: - dts/*/gigadevice/ - dts/bindings/*/*gd32* - soc/arm/gigadevice/ - - soc/riscv/riscv-privileged/gd32vf103/ + - soc/riscv/gd_gd32/ - scripts/west_commands/*/*gd32* labels: - "platform: GD32" @@ -3384,7 +3386,7 @@ ITE Platforms: - drivers/*/*it8xxx2*.c - dts/bindings/*/*ite* - dts/riscv/ite/ - - soc/riscv/riscv-ite/ + - soc/riscv/ite_ec/ labels: - "platform: ITE" @@ -3474,6 +3476,15 @@ Infineon Platforms: Infineon SOCs, dts files and related drivers. Infineon Proto, Pioneer, Eval and Relax boards. +Panasonic Platforms: + status: maintained + maintainers: + - pideu-sj + files: + - boards/arm/pan17*/ + labels: + - "platform: Panasonic" + RTIO: status: maintained maintainers: diff --git a/arch/arc/core/CMakeLists.txt b/arch/arc/core/CMakeLists.txt index 3325e27ff88ed4e..00c9f775038247d 100644 --- a/arch/arc/core/CMakeLists.txt +++ b/arch/arc/core/CMakeLists.txt @@ -26,7 +26,7 @@ zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S) zephyr_library_sources_ifdef(CONFIG_ARC_CONNECT arc_connect.c) -zephyr_library_sources_ifdef(CONFIG_ARC_CONNECT arc_smp.c) +zephyr_library_sources_ifdef(CONFIG_ARC_CONNECT smp.c) zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c) diff --git a/arch/arc/core/cache.c b/arch/arc/core/cache.c index 1536c5a173f2b0a..8c2aab29fed5dbf 100644 --- a/arch/arc/core/cache.c +++ b/arch/arc/core/cache.c @@ -218,8 +218,7 @@ int arch_icache_flush_and_invd_range(void *addr, size_t size) static int init_dcache(void) { - - arch_dcache_enable(); + sys_cache_data_enable(); #if defined(CONFIG_DCACHE_LINE_SIZE_DETECT) init_dcache_line_size(); diff --git a/arch/arc/core/reset.S b/arch/arc/core/reset.S index 82ea4c4d435c7a1..0894875dcac3600 100644 --- a/arch/arc/core/reset.S +++ b/arch/arc/core/reset.S @@ -174,7 +174,7 @@ _slave_core_wait: jl z_arc_firq_stack_set pop r0 #endif - j z_arc_slave_start + j arch_secondary_cpu_init _master_core_startup: #endif diff --git a/arch/arc/core/arc_smp.c b/arch/arc/core/smp.c similarity index 96% rename from arch/arc/core/arc_smp.c rename to arch/arc/core/smp.c index 9fb43c411524168..6bc89883fad999d 100644 --- a/arch/arc/core/arc_smp.c +++ b/arch/arc/core/smp.c @@ -89,7 +89,7 @@ static void arc_connect_debug_mask_update(int cpu_num) void arc_core_private_intc_init(void); /* the C entry of slave cores */ -void z_arc_slave_start(int cpu_num) +void arch_secondary_cpu_init(int cpu_num) { arch_cpustart_t fn; @@ -145,7 +145,7 @@ void arch_sched_ipi(void) } } -static int arc_smp_init(void) +int arch_smp_init(void) { struct arc_connect_bcr bcr; @@ -188,6 +188,5 @@ static int arc_smp_init(void) return 0; } - -SYS_INIT(arc_smp_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +SYS_INIT(arch_smp_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); #endif diff --git a/arch/arm/core/cortex_a_r/reset.S b/arch/arm/core/cortex_a_r/reset.S index 362f4aa214f31f5..0b107fbf596afc7 100644 --- a/arch/arm/core/cortex_a_r/reset.S +++ b/arch/arm/core/cortex_a_r/reset.S @@ -217,7 +217,7 @@ EL1_Reset_Handler: bne 1b /* we can now move on */ - ldr r4, =z_arm_secondary_start + ldr r4, =arch_secondary_cpu_init ldr r5, [r0, #BOOT_PARAM_FIQ_SP_OFFSET] ldr r6, [r0, #BOOT_PARAM_IRQ_SP_OFFSET] ldr r7, [r0, #BOOT_PARAM_ABT_SP_OFFSET] diff --git a/arch/arm/core/cortex_a_r/smp.c b/arch/arm/core/cortex_a_r/smp.c index 2aeb36c1735a85a..f581c7703104060 100644 --- a/arch/arm/core/cortex_a_r/smp.c +++ b/arch/arm/core/cortex_a_r/smp.c @@ -148,7 +148,7 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, arch_cpustart_ * \todo Support PSCI */ - /* Wait secondary cores up, see z_arm64_secondary_start */ + /* Wait secondary cores up, see arch_secondary_cpu_init */ while (arm_cpu_boot_params.fn) { wfe(); } @@ -159,7 +159,7 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, arch_cpustart_ } /* the C entry of secondary cores */ -void z_arm_secondary_start(void) +void arch_secondary_cpu_init(void) { int cpu_num = arm_cpu_boot_params.cpu_num; arch_cpustart_t fn; @@ -245,7 +245,7 @@ void arch_sched_ipi(void) broadcast_ipi(SGI_SCHED_IPI); } -static int arm_smp_init(void) +int arch_smp_init(void) { cpu_map[0] = MPIDR_TO_CORE(GET_MPIDR()); @@ -259,6 +259,6 @@ static int arm_smp_init(void) return 0; } -SYS_INIT(arm_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +SYS_INIT(arch_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); #endif diff --git a/arch/arm/core/cortex_m/scb.c b/arch/arm/core/cortex_m/scb.c index 472c82424658c52..e3c35073ea310f2 100644 --- a/arch/arm/core/cortex_m/scb.c +++ b/arch/arm/core/cortex_m/scb.c @@ -21,6 +21,7 @@ #include #include #include +#include #if defined(CONFIG_CPU_HAS_NXP_MPU) #include @@ -120,15 +121,27 @@ void z_arm_init_arch_hw_at_boot(void) * reset it to a known clean state. */ if (SCB->CCR & SCB_CCR_DC_Msk) { - sys_cache_data_disable(); + /* + * Do not use sys_cache_data_disable at this point, but instead + * the architecture specific function. This ensures that the + * cache is disabled although CONFIG_CACHE_MANAGEMENT might be + * disabled. + */ + SCB_DisableDCache(); } else { - sys_cache_data_invd_all(); + SCB_InvalidateDCache(); } #endif /* CONFIG_DCACHE */ #if defined(CONFIG_ICACHE) - /* Reset I-Cache settings. */ - sys_cache_instr_disable(); + /* + * Reset I-Cache settings. + * Do not use sys_cache_data_disable at this point, but instead + * the architecture specific function. This ensures that the + * cache is disabled although CONFIG_CACHE_MANAGEMENT might be + * disabled. + */ + SCB_DisableICache(); #endif /* CONFIG_ICACHE */ #endif /* CONFIG_ARCH_CACHE */ diff --git a/arch/arm64/core/fatal.c b/arch/arm64/core/fatal.c index 1139a818e1f387f..dbf0c4cdae17c9e 100644 --- a/arch/arm64/core/fatal.c +++ b/arch/arm64/core/fatal.c @@ -250,7 +250,7 @@ static bool z_arm64_stack_corruption_check(z_arch_esf_t *esf, uint64_t esr, uint * so flush the fpu context to its owner, and then set no fpu trap to avoid * a new nested exception triggered by FPU accessing (var_args). */ - z_arm64_flush_local_fpu(); + arch_flush_local_fpu(); write_cpacr_el1(read_cpacr_el1() | CPACR_EL1_FPEN_NOTRAP); #endif arch_curr_cpu()->arch.corrupted_sp = 0UL; diff --git a/arch/arm64/core/fpu.c b/arch/arm64/core/fpu.c index 74a32b8009c8676..0133eed2dcaaf6c 100644 --- a/arch/arm64/core/fpu.c +++ b/arch/arm64/core/fpu.c @@ -64,7 +64,7 @@ static inline void DBG(char *msg, struct k_thread *t) { } * Flush FPU content and disable access. * This is called locally and also from flush_fpu_ipi_handler(). */ -void z_arm64_flush_local_fpu(void) +void arch_flush_local_fpu(void) { __ASSERT(read_daif() & DAIF_IRQ_BIT, "must be called with IRQs disabled"); @@ -107,10 +107,10 @@ static void flush_owned_fpu(struct k_thread *thread) } /* we found it live on CPU i */ if (i == _current_cpu->id) { - z_arm64_flush_local_fpu(); + arch_flush_local_fpu(); } else { /* the FPU context is live on another CPU */ - z_arm64_flush_fpu_ipi(i); + arch_flush_fpu_ipi(i); /* * Wait for it only if this is about the thread @@ -126,7 +126,7 @@ static void flush_owned_fpu(struct k_thread *thread) * two CPUs want to pull each other's FPU context. */ if (thread == _current) { - z_arm64_flush_local_fpu(); + arch_flush_local_fpu(); while (atomic_ptr_get(&_kernel.cpus[i].arch.fpu_owner) == thread) { barrier_dsync_fence_full(); } @@ -334,7 +334,7 @@ int arch_float_disable(struct k_thread *thread) flush_owned_fpu(thread); #else if (thread == atomic_ptr_get(&_current_cpu->arch.fpu_owner)) { - z_arm64_flush_local_fpu(); + arch_flush_local_fpu(); } #endif diff --git a/arch/arm64/core/prep_c.c b/arch/arm64/core/prep_c.c index 8ec380296aac7e2..bfd3b7c1eaa90ec 100644 --- a/arch/arm64/core/prep_c.c +++ b/arch/arm64/core/prep_c.c @@ -69,11 +69,12 @@ void z_prep_c(void) CODE_UNREACHABLE; } + #if CONFIG_MP_MAX_NUM_CPUS > 1 -extern FUNC_NORETURN void z_arm64_secondary_start(void); +extern FUNC_NORETURN void arch_secondary_cpu_init(void); void z_arm64_secondary_prep_c(void) { - z_arm64_secondary_start(); + arch_secondary_cpu_init(); CODE_UNREACHABLE; } diff --git a/arch/arm64/core/smp.c b/arch/arm64/core/smp.c index e67032eb2a4804d..20faef061089f8a 100644 --- a/arch/arm64/core/smp.c +++ b/arch/arm64/core/smp.c @@ -122,7 +122,7 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, k_panic(); } - /* Wait secondary cores up, see z_arm64_secondary_start */ + /* Wait secondary cores up, see arch_secondary_cpu_init */ while (arm64_cpu_boot_params.fn) { wfe(); } @@ -133,9 +133,9 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, } /* the C entry of secondary cores */ -void z_arm64_secondary_start(void) +void arch_secondary_cpu_init(int cpu_num) { - int cpu_num = arm64_cpu_boot_params.cpu_num; + cpu_num = arm64_cpu_boot_params.cpu_num; arch_cpustart_t fn; void *arg; @@ -242,11 +242,11 @@ void flush_fpu_ipi_handler(const void *unused) ARG_UNUSED(unused); disable_irq(); - z_arm64_flush_local_fpu(); + arch_flush_local_fpu(); /* no need to re-enable IRQs here */ } -void z_arm64_flush_fpu_ipi(unsigned int cpu) +void arch_flush_fpu_ipi(unsigned int cpu) { const uint64_t mpidr = cpu_map[cpu]; uint8_t aff0; @@ -272,14 +272,14 @@ void arch_spin_relax(void) arm_gic_irq_clear_pending(SGI_FPU_IPI); /* * We may not be in IRQ context here hence cannot use - * z_arm64_flush_local_fpu() directly. + * arch_flush_local_fpu() directly. */ arch_float_disable(_current_cpu->arch.fpu_owner); } } #endif -static int arm64_smp_init(void) +int arch_smp_init(void) { cpu_map[0] = MPIDR_TO_CORE(GET_MPIDR()); @@ -302,6 +302,6 @@ static int arm64_smp_init(void) return 0; } -SYS_INIT(arm64_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +SYS_INIT(arch_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); #endif diff --git a/arch/arm64/include/kernel_arch_func.h b/arch/arm64/include/kernel_arch_func.h index 3b028b10b3772b3..a5c3d59d87a6ff6 100644 --- a/arch/arm64/include/kernel_arch_func.h +++ b/arch/arm64/include/kernel_arch_func.h @@ -48,8 +48,8 @@ extern void z_arm64_set_ttbr0(uint64_t ttbr0); extern void z_arm64_mem_cfg_ipi(void); #ifdef CONFIG_FPU_SHARING -void z_arm64_flush_local_fpu(void); -void z_arm64_flush_fpu_ipi(unsigned int cpu); +void arch_flush_local_fpu(void); +void arch_flush_fpu_ipi(unsigned int cpu); #endif #ifdef CONFIG_ARM64_SAFE_EXCEPTION_STACK diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index a1cefcbdf43a20a..80249670d09ea5e 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -47,6 +47,12 @@ config INCLUDE_RESET_VECTOR Include the reset vector stub, which initializes the stack and prepares for running C code. +config RISCV_PRIVILEGED + bool + select ARCH_HAS_RAMFUNC_SUPPORT if XIP + help + Option selected by SoCs implementing the RISC-V privileged ISA. + config RISCV_SOC_HAS_ISR_STACKING bool depends on !USERSPACE @@ -333,7 +339,7 @@ config RISCV_TRAP_HANDLER_ALIGNMENT The minimum alignment is 4 bytes according to the Spec. config GEN_IRQ_VECTOR_TABLE - select RISCV_VECTORED_MODE if SOC_FAMILY_RISCV_PRIVILEGED + select RISCV_VECTORED_MODE if RISCV_PRIVILEGED config ARCH_HAS_SINGLE_THREAD_SUPPORT default y if !SMP diff --git a/arch/riscv/core/fpu.c b/arch/riscv/core/fpu.c index 293a5bc613fcb2c..da5d07b31464043 100644 --- a/arch/riscv/core/fpu.c +++ b/arch/riscv/core/fpu.c @@ -98,7 +98,7 @@ static void z_riscv_fpu_load(void) * * This is called locally and also from flush_fpu_ipi_handler(). */ -void z_riscv_flush_local_fpu(void) +void arch_flush_local_fpu(void) { __ASSERT((csr_read(mstatus) & MSTATUS_IEN) == 0, "must be called with IRQs disabled"); @@ -149,11 +149,11 @@ static void flush_owned_fpu(struct k_thread *thread) /* we found it live on CPU i */ if (i == _current_cpu->id) { z_riscv_fpu_disable(); - z_riscv_flush_local_fpu(); + arch_flush_local_fpu(); break; } /* the FPU context is live on another CPU */ - z_riscv_flush_fpu_ipi(i); + arch_flush_fpu_ipi(i); /* * Wait for it only if this is about the thread @@ -170,7 +170,7 @@ static void flush_owned_fpu(struct k_thread *thread) */ if (thread == _current) { z_riscv_fpu_disable(); - z_riscv_flush_local_fpu(); + arch_flush_local_fpu(); do { arch_nop(); owner = atomic_ptr_get(&_kernel.cpus[i].arch.fpu_owner); @@ -211,7 +211,7 @@ void z_riscv_fpu_trap(z_arch_esf_t *esf) "called despite FPU being accessible"); /* save current owner's content if any */ - z_riscv_flush_local_fpu(); + arch_flush_local_fpu(); if (_current->arch.exception_depth > 0) { /* @@ -271,7 +271,7 @@ static bool fpu_access_allowed(unsigned int exc_update_level) * to come otherwise. */ z_riscv_fpu_disable(); - z_riscv_flush_local_fpu(); + arch_flush_local_fpu(); #ifdef CONFIG_SMP flush_owned_fpu(_current); #endif @@ -329,7 +329,7 @@ int arch_float_disable(struct k_thread *thread) #else if (thread == _current_cpu->arch.fpu_owner) { z_riscv_fpu_disable(); - z_riscv_flush_local_fpu(); + arch_flush_local_fpu(); } #endif diff --git a/arch/riscv/core/reset.S b/arch/riscv/core/reset.S index 73e2bf923a2d80c..e9424e7a8e2af26 100644 --- a/arch/riscv/core/reset.S +++ b/arch/riscv/core/reset.S @@ -19,7 +19,7 @@ GTEXT(__reset) GTEXT(z_prep_c) GTEXT(riscv_cpu_wake_flag) GTEXT(riscv_cpu_sp) -GTEXT(z_riscv_secondary_cpu_init) +GTEXT(arch_secondary_cpu_init) #if CONFIG_INCLUDE_RESET_VECTOR SECTION_FUNC(reset, __reset) @@ -111,7 +111,7 @@ wait_secondary_wake_flag: la t0, riscv_cpu_boot_flag li t1, 1 sr t1, 0(t0) - j z_riscv_secondary_cpu_init + j arch_secondary_cpu_init #else j loop_unconfigured_cores #endif diff --git a/arch/riscv/core/smp.c b/arch/riscv/core/smp.c index 6154450e58d2a6a..b49fcf8aa4f4544 100644 --- a/arch/riscv/core/smp.c +++ b/arch/riscv/core/smp.c @@ -43,7 +43,7 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, } } -void z_riscv_secondary_cpu_init(int hartid) +void arch_secondary_cpu_init(int hartid) { unsigned int i; unsigned int cpu_num = 0; @@ -97,14 +97,14 @@ void arch_sched_ipi(void) } #ifdef CONFIG_FPU_SHARING -void z_riscv_flush_fpu_ipi(unsigned int cpu) +void arch_flush_fpu_ipi(unsigned int cpu) { atomic_set_bit(&cpu_pending_ipi[cpu], IPI_FPU_FLUSH); MSIP(_kernel.cpus[cpu].arch.hartid) = 1; } #endif -static void ipi_handler(const void *unused) +static void sched_ipi_handler(const void *unused) { ARG_UNUSED(unused); @@ -120,7 +120,7 @@ static void ipi_handler(const void *unused) /* disable IRQs */ csr_clear(mstatus, MSTATUS_IEN); /* perform the flush */ - z_riscv_flush_local_fpu(); + arch_flush_local_fpu(); /* * No need to re-enable IRQs here as long as * this remains the last case. @@ -144,21 +144,20 @@ void arch_spin_relax(void) if (atomic_test_and_clear_bit(pending_ipi, IPI_FPU_FLUSH)) { /* * We may not be in IRQ context here hence cannot use - * z_riscv_flush_local_fpu() directly. + * arch_flush_local_fpu() directly. */ arch_float_disable(_current_cpu->arch.fpu_owner); } } #endif -static int riscv_smp_init(void) +int arch_smp_init(void) { - IRQ_CONNECT(RISCV_MACHINE_SOFT_IRQ, 0, ipi_handler, NULL, 0); + IRQ_CONNECT(RISCV_MACHINE_SOFT_IRQ, 0, sched_ipi_handler, NULL, 0); irq_enable(RISCV_MACHINE_SOFT_IRQ); return 0; } - -SYS_INIT(riscv_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +SYS_INIT(arch_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); #endif /* CONFIG_SMP */ diff --git a/arch/riscv/include/kernel_arch_func.h b/arch/riscv/include/kernel_arch_func.h index fdd39eb8a688746..b639f09c6c6899d 100644 --- a/arch/riscv/include/kernel_arch_func.h +++ b/arch/riscv/include/kernel_arch_func.h @@ -95,8 +95,8 @@ int z_irq_do_offload(void); #endif #ifdef CONFIG_FPU_SHARING -void z_riscv_flush_local_fpu(void); -void z_riscv_flush_fpu_ipi(unsigned int cpu); +void arch_flush_local_fpu(void); +void arch_flush_fpu_ipi(unsigned int cpu); #endif #ifndef CONFIG_MULTITHREADING diff --git a/arch/x86/core/ia32/gdbstub.c b/arch/x86/core/ia32/gdbstub.c index 41b6a4500fffc6f..692ea78baf41cb6 100644 --- a/arch/x86/core/ia32/gdbstub.c +++ b/arch/x86/core/ia32/gdbstub.c @@ -174,12 +174,8 @@ size_t arch_gdb_reg_readone(struct gdb_ctx *ctx, uint8_t *buf, size_t buflen, * registers instead of stopping in the middle of * "info registers all". */ - if (buflen >= 2) { - memcpy(buf, "xx", 2); - ret = 2; - } else { - ret = 0; - } + memcpy(buf, "xx", 2); + ret = 2; } else { ret = bin2hex((const uint8_t *)&(ctx->registers[regno]), sizeof(ctx->registers[regno]), diff --git a/arch/x86/core/intel64.cmake b/arch/x86/core/intel64.cmake index cd37d5c497e4515..1cb25ebe220e580 100644 --- a/arch/x86/core/intel64.cmake +++ b/arch/x86/core/intel64.cmake @@ -15,7 +15,8 @@ zephyr_library_sources( intel64/thread.c intel64/fatal.c ) - +zephyr_library_sources_ifdef(CONFIG_SMP intel64/smp.c) +zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD intel64/irq_offload.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE intel64/userspace.S) zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE intel64/tls.c) zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP intel64/coredump.c) diff --git a/arch/x86/core/intel64/irq.c b/arch/x86/core/intel64/irq.c index a730427174629c5..f8e251b804613c6 100644 --- a/arch/x86/core/intel64/irq.c +++ b/arch/x86/core/intel64/irq.c @@ -13,18 +13,11 @@ #include #include #include -#include + LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); unsigned char _irq_to_interrupt_vector[CONFIG_MAX_IRQ_LINES]; - -/* - * The low-level interrupt code consults these arrays to dispatch IRQs, so - * so be sure to keep locore.S up to date with any changes. Note the indices: - * use (vector - IV_IRQS), since exception vectors do not appear here. - */ - #define NR_IRQ_VECTORS (IV_NR_VECTORS - IV_IRQS) /* # vectors free for IRQs */ void (*x86_irq_funcs[NR_IRQ_VECTORS])(const void *arg); @@ -138,45 +131,6 @@ int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, return vector; } -#ifdef CONFIG_IRQ_OFFLOAD -#include - -void arch_irq_offload(irq_offload_routine_t routine, const void *parameter) -{ - x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = routine; - x86_irq_args[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = parameter; - __asm__ volatile("int %0" : : "i" (CONFIG_IRQ_OFFLOAD_VECTOR) - : "memory"); - x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = NULL; -} - -#endif /* CONFIG_IRQ_OFFLOAD */ - -#if defined(CONFIG_SMP) - -void z_x86_ipi_setup(void) -{ - /* - * z_sched_ipi() doesn't have the same signature as a typical ISR, so - * we fudge it with a cast. the argument is ignored, no harm done. - */ - - x86_irq_funcs[CONFIG_SCHED_IPI_VECTOR - IV_IRQS] = - (void *) z_sched_ipi; - - /* TLB shootdown handling */ - x86_irq_funcs[CONFIG_TLB_IPI_VECTOR - IV_IRQS] = z_x86_tlb_ipi; -} - -/* - * it is not clear exactly how/where/why to abstract this, as it - * assumes the use of a local APIC (but there's no other mechanism). - */ -void arch_sched_ipi(void) -{ - z_loapic_ipi(0, LOAPIC_ICR_IPI_OTHERS, CONFIG_SCHED_IPI_VECTOR); -} -#endif /* The first bit is used to indicate whether the list of reserved interrupts * have been initialized based on content stored in the irq_alloc linker diff --git a/arch/x86/core/intel64/irq_offload.c b/arch/x86/core/intel64/irq_offload.c new file mode 100644 index 000000000000000..0146321f7d9d99a --- /dev/null +++ b/arch/x86/core/intel64/irq_offload.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Intel corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file IRQ offload - x8664 implementation + */ + +#include +#include +#include + +#define NR_IRQ_VECTORS (IV_NR_VECTORS - IV_IRQS) /* # vectors free for IRQs */ + +extern void (*x86_irq_funcs[NR_IRQ_VECTORS])(const void *arg); +extern const void *x86_irq_args[NR_IRQ_VECTORS]; + + +void arch_irq_offload(irq_offload_routine_t routine, const void *parameter) +{ + x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = routine; + x86_irq_args[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = parameter; + __asm__ volatile("int %0" : : "i" (CONFIG_IRQ_OFFLOAD_VECTOR) + : "memory"); + x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = NULL; +} diff --git a/arch/x86/core/intel64/smp.c b/arch/x86/core/intel64/smp.c new file mode 100644 index 000000000000000..a73ba9c8f38c363 --- /dev/null +++ b/arch/x86/core/intel64/smp.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include + +#define NR_IRQ_VECTORS (IV_NR_VECTORS - IV_IRQS) /* # vectors free for IRQs */ + +extern void (*x86_irq_funcs[NR_IRQ_VECTORS])(const void *arg); +extern const void *x86_irq_args[NR_IRQ_VECTORS]; + + +int arch_smp_init(void) +{ + /* + * z_sched_ipi() doesn't have the same signature as a typical ISR, so + * we fudge it with a cast. the argument is ignored, no harm done. + */ + + x86_irq_funcs[CONFIG_SCHED_IPI_VECTOR - IV_IRQS] = + (void *) z_sched_ipi; + + /* TLB shootdown handling */ + x86_irq_funcs[CONFIG_TLB_IPI_VECTOR - IV_IRQS] = z_x86_tlb_ipi; + return 0; +} + +/* + * it is not clear exactly how/where/why to abstract this, as it + * assumes the use of a local APIC (but there's no other mechanism). + */ +void arch_sched_ipi(void) +{ + z_loapic_ipi(0, LOAPIC_ICR_IPI_OTHERS, CONFIG_SCHED_IPI_VECTOR); +} + +SYS_INIT(arch_smp_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/arch/x86/core/prep_c.c b/arch/x86/core/prep_c.c index d067e067641cb24..17a4a7f74734337 100644 --- a/arch/x86/core/prep_c.c +++ b/arch/x86/core/prep_c.c @@ -74,7 +74,7 @@ FUNC_NORETURN void z_prep_c(void *arg) #endif #if defined(CONFIG_SMP) - z_x86_ipi_setup(); + arch_smp_init(); #endif z_cstart(); diff --git a/boards/arm/adafruit_kb2040/adafruit_kb2040-pinctrl.dtsi b/boards/arm/adafruit_kb2040/adafruit_kb2040-pinctrl.dtsi index cf4eeaf6b956d14..cf1289acedc34c7 100644 --- a/boards/arm/adafruit_kb2040/adafruit_kb2040-pinctrl.dtsi +++ b/boards/arm/adafruit_kb2040/adafruit_kb2040-pinctrl.dtsi @@ -50,4 +50,10 @@ clocks_default: clocks_default { }; + + ws2812_pio0_default: ws2812_pio0_default { + ws2812 { + pinmux = ; + }; + }; }; diff --git a/boards/arm/adafruit_kb2040/adafruit_kb2040.dts b/boards/arm/adafruit_kb2040/adafruit_kb2040.dts index 1abbb70e9884c66..c17700aa8fa1141 100644 --- a/boards/arm/adafruit_kb2040/adafruit_kb2040.dts +++ b/boards/arm/adafruit_kb2040/adafruit_kb2040.dts @@ -11,6 +11,7 @@ #include "adafruit_kb2040-pinctrl.dtsi" #include "sparkfun_pro_micro_connector.dtsi" #include +#include / { chosen { @@ -24,6 +25,7 @@ aliases { watchdog0 = &wdt0; + led-strip = &ws2812; }; }; @@ -94,6 +96,29 @@ pinctrl-names = "default"; }; +&pio0 { + status = "okay"; + + pio-ws2812 { + compatible = "worldsemi,ws2812-rpi_pico-pio"; + status = "okay"; + pinctrl-0 = <&ws2812_pio0_default>; + pinctrl-names = "default"; + bit-waveform = <3>, <3>, <4>; + + ws2812: ws2812 { + status = "okay"; + output-pin = <17>; + chain-length = <1>; + color-mapping = ; + reset-delay = <280>; + frequency = <800000>; + }; + }; +}; + zephyr_udc0: &usbd { status = "okay"; }; diff --git a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble-common.dtsi b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble-common.dtsi index 200db7f94c7a11e..3d31ede313fea1f 100644 --- a/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble-common.dtsi +++ b/boards/arm/arduino_nano_33_ble/arduino_nano_33_ble-common.dtsi @@ -189,6 +189,10 @@ arduino_spi: &spi2 { status = "okay"; }; +&gpiote { + status = "okay"; +}; + &pwm0 { status = "okay"; pinctrl-0 = <&pwm0_default>; diff --git a/boards/arm/arduino_opta_m4/doc/index.rst b/boards/arm/arduino_opta_m4/doc/index.rst index be914c3fa486837..90f9497db33a446 100644 --- a/boards/arm/arduino_opta_m4/doc/index.rst +++ b/boards/arm/arduino_opta_m4/doc/index.rst @@ -71,7 +71,7 @@ Pin Mapping ARDUINO OPTA M4 has access to the 9 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `ARDUINO-OPTA website`_. +For more details please refer to `ARDUINO-OPTA website`_. Default Zephyr Peripheral Mapping --------------------------------- diff --git a/boards/arm/ast1030_evb/ast1030_evb_defconfig b/boards/arm/ast1030_evb/ast1030_evb_defconfig index 6a0e696b39bfe02..62278d4421327d1 100644 --- a/boards/arm/ast1030_evb/ast1030_evb_defconfig +++ b/boards/arm/ast1030_evb/ast1030_evb_defconfig @@ -5,7 +5,6 @@ CONFIG_SOC_SERIES_AST10X0=y CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=200000000 CONFIG_MAIN_STACK_SIZE=4096 -CONFIG_BOOTLOADER_SRAM_SIZE=0 CONFIG_FLASH_SIZE=0 CONFIG_FLASH_BASE_ADDRESS=0x0 CONFIG_XIP=n diff --git a/boards/arm/atsamc21n_xpro/doc/index.rst b/boards/arm/atsamc21n_xpro/doc/index.rst index bb060fe32a46ce9..e7d7d2d58525cdb 100644 --- a/boards/arm/atsamc21n_xpro/doc/index.rst +++ b/boards/arm/atsamc21n_xpro/doc/index.rst @@ -86,7 +86,7 @@ Pin Mapping The SAM C21N Xplained Pro evaluation kit has 4 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `SAM C21 Family Datasheet`_ and the `SAM C21N +For more details please refer to `SAM C21 Family Datasheet`_ and the `SAM C21N Xplained Pro Schematic`_. Default Zephyr Peripheral Mapping: diff --git a/boards/arm/atsamd21_xpro/doc/index.rst b/boards/arm/atsamd21_xpro/doc/index.rst index 9732c84d6fbf215..78ed6da63ffebd9 100644 --- a/boards/arm/atsamd21_xpro/doc/index.rst +++ b/boards/arm/atsamd21_xpro/doc/index.rst @@ -87,7 +87,7 @@ Pin Mapping The SAM D21 Xplained Pro evaluation kit has 3 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `SAM D21 Family Datasheet`_ and the `SAM D21 +For more details please refer to `SAM D21 Family Datasheet`_ and the `SAM D21 Xplained Pro Schematic`_. .. image:: img/ATSAMD21-XPRO-pinout.jpg diff --git a/boards/arm/atsaml21_xpro/doc/index.rst b/boards/arm/atsaml21_xpro/doc/index.rst index 2051b9efa189096..5c55f23d5874e72 100644 --- a/boards/arm/atsaml21_xpro/doc/index.rst +++ b/boards/arm/atsaml21_xpro/doc/index.rst @@ -81,7 +81,7 @@ Pin Mapping The SAM L21 Xplained Pro evaluation kit has 2 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `SAM L21 Family Datasheet`_ and the `SAM L21 +For more details please refer to `SAM L21 Family Datasheet`_ and the `SAM L21 Xplained Pro Schematic`_. .. image:: img/atsaml21-xpro-pinout.jpg diff --git a/boards/arm/atsamr21_xpro/doc/index.rst b/boards/arm/atsamr21_xpro/doc/index.rst index da9cb14a4370979..60d2c36ea3226b5 100644 --- a/boards/arm/atsamr21_xpro/doc/index.rst +++ b/boards/arm/atsamr21_xpro/doc/index.rst @@ -64,7 +64,7 @@ Pin Mapping The SAM R21 Xplained Pro evaluation kit has 3 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `SAM R21 Family Datasheet`_ and the `SAM R21 +For more details please refer to `SAM R21 Family Datasheet`_ and the `SAM R21 Xplained Pro Schematic`_. .. image:: img/ATSAMR21-XPRO-pinout.jpg diff --git a/boards/arm/atsamr34_xpro/doc/index.rst b/boards/arm/atsamr34_xpro/doc/index.rst index 051245c5d392a67..6347b50dedbd673 100644 --- a/boards/arm/atsamr34_xpro/doc/index.rst +++ b/boards/arm/atsamr34_xpro/doc/index.rst @@ -99,7 +99,7 @@ Pin Mapping The SAM R34 Xplained Pro evaluation kit has 3 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `SAM R34 Family Datasheet`_ and the `SAM R34 +For more details please refer to `SAM R34 Family Datasheet`_ and the `SAM R34 Xplained Pro Schematic`_. .. image:: img/atsamr34-xpro-pinout.jpg diff --git a/boards/arm/b_g474e_dpow1/doc/index.rst b/boards/arm/b_g474e_dpow1/doc/index.rst index 1959ab6ad6802e4..75d99572fbf24e4 100644 --- a/boards/arm/b_g474e_dpow1/doc/index.rst +++ b/boards/arm/b_g474e_dpow1/doc/index.rst @@ -99,7 +99,7 @@ Default Zephyr Peripheral Mapping: - UCPD CC2 : PB4 - UCPD CC1 : PB6 -For mode details please refer to `B-G474E-DPOW1 Discovery board User Manual`_. +For more details please refer to `B-G474E-DPOW1 Discovery board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.dts b/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.dts index fe6322cc26b007c..c51161814327db5 100644 --- a/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.dts +++ b/boards/arm/b_l4s5i_iot01a/b_l4s5i_iot01a.dts @@ -148,16 +148,15 @@ pinctrl-names = "default"; status = "okay"; - cs-gpios = <&gpiod 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + cs-gpios = <&gpiod 13 GPIO_ACTIVE_LOW>, <&gpioe 0 GPIO_ACTIVE_LOW>; spbtle-rf@0 { - compatible = "zephyr,bt-hci-spi", "st,hci-spi-v1"; + compatible = "st,hci-spi-v1"; reg = <0>; - reset-gpios = <&gpioa 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + reset-gpios = <&gpioa 8 GPIO_ACTIVE_LOW>; irq-gpios = <&gpioe 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; - spi-max-frequency = <2000000>; - controller-data-delay-us = <0>; /* No need for extra delay for BlueNRG-MS */ + spi-max-frequency = ; spi-hold-cs; }; diff --git a/boards/arm/b_l4s5i_iot01a/doc/index.rst b/boards/arm/b_l4s5i_iot01a/doc/index.rst index 14d9480707b0117..d5b11c8b30b3ab9 100644 --- a/boards/arm/b_l4s5i_iot01a/doc/index.rst +++ b/boards/arm/b_l4s5i_iot01a/doc/index.rst @@ -144,7 +144,7 @@ Connections and IOs B_L4S5I_IOT01A Discovery kit has 9 GPIO controllers (from A to I). These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `B L47S5I IOT01A board User Manual`_. +For more details please refer to `B L47S5I IOT01A board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/b_u585i_iot02a/doc/index.rst b/boards/arm/b_u585i_iot02a/doc/index.rst index 3c794b4de792635..56906f5ff08f27b 100644 --- a/boards/arm/b_u585i_iot02a/doc/index.rst +++ b/boards/arm/b_u585i_iot02a/doc/index.rst @@ -245,7 +245,7 @@ Connections and IOs B_U585I_IOT02A Discovery kit has 9 GPIO controllers (from A to I). These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `B U585I IOT02A board User Manual`_. +For more details please refer to `B U585I IOT02A board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/bl654_usb/bl654_usb.dts b/boards/arm/bl654_usb/bl654_usb.dts index 80600290dbff241..fa814f4b80e421f 100644 --- a/boards/arm/bl654_usb/bl654_usb.dts +++ b/boards/arm/bl654_usb/bl654_usb.dts @@ -59,6 +59,10 @@ status = "okay"; }; +&gpiote { + status = "okay"; +}; + &pwm0 { status = "okay"; pinctrl-0 = <&pwm0_default>; diff --git a/boards/arm/disco_l475_iot1/disco_l475_iot1.dts b/boards/arm/disco_l475_iot1/disco_l475_iot1.dts index 85e0dcea3c2de61..9ae6399e62ea68a 100644 --- a/boards/arm/disco_l475_iot1/disco_l475_iot1.dts +++ b/boards/arm/disco_l475_iot1/disco_l475_iot1.dts @@ -187,16 +187,15 @@ pinctrl-0 = <&spi3_sck_pc10 &spi3_miso_pc11 &spi3_mosi_pc12>; pinctrl-names = "default"; - cs-gpios = <&gpiod 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + cs-gpios = <&gpiod 13 GPIO_ACTIVE_LOW>, <&gpioe 0 GPIO_ACTIVE_LOW>; spbtle-rf@0 { - compatible = "zephyr,bt-hci-spi", "st,hci-spi-v1"; + compatible = "st,hci-spi-v1"; reg = <0>; - reset-gpios = <&gpioa 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + reset-gpios = <&gpioa 8 GPIO_ACTIVE_LOW>; irq-gpios = <&gpioe 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; - spi-max-frequency = <2000000>; - controller-data-delay-us = <0>; /* No need for extra delay for BlueNRG-MS */ + spi-max-frequency = ; spi-hold-cs; }; diff --git a/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a-pinctrl.dtsi b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a-pinctrl.dtsi new file mode 100644 index 000000000000000..71d2020569185f7 --- /dev/null +++ b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a-pinctrl.dtsi @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for usart0 device, default state - operating as UART */ + usart0_default: usart0_default { + group1 { + psels = , + , + , + ; + }; + }; +}; diff --git a/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.dts b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.dts index 1ff034899dbbff6..5dcae30fbee99e5 100644 --- a/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.dts +++ b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include +#include "efm32gg_sltb009a-pinctrl.dtsi" / { model = "Silicon Labs EFM32GG SLTB009A board"; @@ -57,8 +58,8 @@ &usart0 { current-speed = <115200>; - location-rx = ; - location-tx = ; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; status = "okay"; }; diff --git a/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a-pinctrl.dtsi b/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a-pinctrl.dtsi new file mode 100644 index 000000000000000..24b51c33612b1f0 --- /dev/null +++ b/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a-pinctrl.dtsi @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for usart0 device, default state - operating as UART */ + usart0_default: usart0_default { + group1 { + psels = , + , + , + ; + }; + }; +}; diff --git a/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi b/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi index cb0209f8e4a4a88..6611bee4956d091 100644 --- a/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi +++ b/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi @@ -5,6 +5,7 @@ */ #include +#include "efm32pg_stk3401a-pinctrl.dtsi" / { model = "Silicon Labs EFM32PG STK3401A board"; @@ -60,8 +61,8 @@ &usart0 { current-speed = <115200>; - location-rx = ; - location-tx = ; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; status = "okay"; }; diff --git a/boards/arm/frdm_k64f/board.cmake b/boards/arm/frdm_k64f/board.cmake index a7302350a26d2db..d2fafeb4a0059e1 100644 --- a/boards/arm/frdm_k64f/board.cmake +++ b/boards/arm/frdm_k64f/board.cmake @@ -1,8 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 board_runner_args(jlink "--device=MK64FN1M0xxx12") +board_runner_args(linkserver "--device=MK64FN1M0xxx12:FRDM-K64F") + board_runner_args(pyocd "--target=k64f") +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/arm/frdm_k64f/doc/index.rst b/boards/arm/frdm_k64f/doc/index.rst index e2fce31a9b172fe..acbf22605613c02 100644 --- a/boards/arm/frdm_k64f/doc/index.rst +++ b/boards/arm/frdm_k64f/doc/index.rst @@ -246,11 +246,23 @@ instructions to update from the CMSIS-DAP bootloader to the DAPLink bootloader. .. group-tab:: OpenSDA DAPLink Onboard (Recommended) - Install the :ref:`pyocd-debug-host-tools` and make sure they are in your search - path. + Install the :ref:`linkserver-debug-host-tools` and make sure they are in your + search path. LinkServer works with the default CMSIS-DAP firmware included in + the on-board debugger. + + Linkserver is the default for this board, ``west flash`` and ``west debug`` will + call the linkserver runner. + + .. code-block:: console + + west flash + + Alternatively, pyOCD can be used to flash and debug the board by using the + ``-r pyocd`` option with West. pyOCD is installed when you complete the + :ref:`gs_python_deps` step in the Getting Started Guide. The runners supported + by NXP are LinkServer and JLink. pyOCD is another potential option, but NXP + does not test or support the pyOCD runner. - Follow the instructions in :ref:`opensda-daplink-onboard-debug-probe` to program - the `OpenSDA DAPLink FRDM-K64F Firmware`_. .. group-tab:: OpenSDA JLink Onboard @@ -269,7 +281,7 @@ instructions to update from the CMSIS-DAP bootloader to the DAPLink bootloader. Add the arguments ``-DBOARD_FLASH_RUNNER=jlink`` and ``-DBOARD_DEBUG_RUNNER=jlink`` when you invoke ``west build`` to override the - default runner from pyOCD to J-Link: + default runner to J-Link: .. zephyr-app-commands:: :zephyr-app: samples/hello_world diff --git a/boards/arm/frdm_k64f/frdm_k64f.yaml b/boards/arm/frdm_k64f/frdm_k64f.yaml index a9e99911776a3ef..b4de8b219e1075c 100644 --- a/boards/arm/frdm_k64f/frdm_k64f.yaml +++ b/boards/arm/frdm_k64f/frdm_k64f.yaml @@ -2,7 +2,7 @@ identifier: frdm_k64f name: NXP FRDM-K64F type: mcu arch: arm -ram: 256 +ram: 192 flash: 1024 toolchain: - zephyr diff --git a/boards/arm/frdm_kw41z/frdm_kw41z.yaml b/boards/arm/frdm_kw41z/frdm_kw41z.yaml index 72c7cb4abf39848..63cffff2786761e 100644 --- a/boards/arm/frdm_kw41z/frdm_kw41z.yaml +++ b/boards/arm/frdm_kw41z/frdm_kw41z.yaml @@ -2,7 +2,7 @@ identifier: frdm_kw41z name: NXP FRDM-KW41Z type: mcu arch: arm -ram: 128 +ram: 96 flash: 512 toolchain: - zephyr diff --git a/boards/arm/gd32e507z_eval/doc/img/gd32e507z_eval.jpg b/boards/arm/gd32e507z_eval/doc/img/gd32e507z_eval.jpg deleted file mode 100644 index f09658eb7b8633e..000000000000000 Binary files a/boards/arm/gd32e507z_eval/doc/img/gd32e507z_eval.jpg and /dev/null differ diff --git a/boards/arm/gd32e507z_eval/doc/img/gd32e507z_eval.webp b/boards/arm/gd32e507z_eval/doc/img/gd32e507z_eval.webp new file mode 100644 index 000000000000000..bad1bd26a4f21c6 Binary files /dev/null and b/boards/arm/gd32e507z_eval/doc/img/gd32e507z_eval.webp differ diff --git a/boards/arm/gd32e507z_eval/doc/index.rst b/boards/arm/gd32e507z_eval/doc/index.rst index 9e7aef4dcd4a031..c3484d8beec8439 100644 --- a/boards/arm/gd32e507z_eval/doc/index.rst +++ b/boards/arm/gd32e507z_eval/doc/index.rst @@ -13,7 +13,7 @@ The GD32E507ZE features a single-core ARM Cortex-M33 MCU which can run up to 180 MHz with flash accesses zero wait states, 512kiB of Flash, 128kiB of SRAM and 112 GPIOs. -.. image:: img/gd32e507z_eval.jpg +.. image:: img/gd32e507z_eval.webp :align: center :alt: gd32e507z_eval diff --git a/boards/arm/gd32f350r_eval/doc/img/gd32f350r_eval.jpg b/boards/arm/gd32f350r_eval/doc/img/gd32f350r_eval.jpg deleted file mode 100644 index 528d07470dd3355..000000000000000 Binary files a/boards/arm/gd32f350r_eval/doc/img/gd32f350r_eval.jpg and /dev/null differ diff --git a/boards/arm/gd32f350r_eval/doc/img/gd32f350r_eval.webp b/boards/arm/gd32f350r_eval/doc/img/gd32f350r_eval.webp new file mode 100644 index 000000000000000..bfa7112f343e443 Binary files /dev/null and b/boards/arm/gd32f350r_eval/doc/img/gd32f350r_eval.webp differ diff --git a/boards/arm/gd32f350r_eval/doc/index.rst b/boards/arm/gd32f350r_eval/doc/index.rst index 35971620c176429..8a2317da68e6782 100644 --- a/boards/arm/gd32f350r_eval/doc/index.rst +++ b/boards/arm/gd32f350r_eval/doc/index.rst @@ -13,7 +13,7 @@ The GD32F350RBT6 features a single-core ARM Cortex-M4F MCU which can run up to 108-MHz with flash accesses zero wait states, 128kB of Flash, 16kB of SRAM and 55 GPIOs. -.. image:: img/gd32f350r_eval.jpg +.. image:: img/gd32f350r_eval.webp :align: center :alt: gd32f350r_eval diff --git a/boards/arm/gd32f403z_eval/Kconfig b/boards/arm/gd32f403z_eval/Kconfig deleted file mode 100644 index 5630f4bbf05ebe8..000000000000000 --- a/boards/arm/gd32f403z_eval/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2021 ATL-Electronics -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_INIT_PRIORITY - int "Board initialization priority" - default 50 - help - Board initialization priority. diff --git a/boards/arm/gd32f407v_start/doc/img/gd32f407v_start.jpg b/boards/arm/gd32f407v_start/doc/img/gd32f407v_start.jpg deleted file mode 100644 index efa513384017105..000000000000000 Binary files a/boards/arm/gd32f407v_start/doc/img/gd32f407v_start.jpg and /dev/null differ diff --git a/boards/arm/gd32f407v_start/doc/img/gd32f407v_start.webp b/boards/arm/gd32f407v_start/doc/img/gd32f407v_start.webp new file mode 100644 index 000000000000000..1badefd1e38826b Binary files /dev/null and b/boards/arm/gd32f407v_start/doc/img/gd32f407v_start.webp differ diff --git a/boards/arm/gd32f407v_start/doc/index.rst b/boards/arm/gd32f407v_start/doc/index.rst index fd24ffb5d644933..cd67921e59e3890 100644 --- a/boards/arm/gd32f407v_start/doc/index.rst +++ b/boards/arm/gd32f407v_start/doc/index.rst @@ -13,7 +13,7 @@ The GD32F407VE features a single-core ARM Cortex-M4 MCU which can run up to 168 MHz with flash accesses zero wait states, 3072kiB of Flash, 192kiB of SRAM and 82 GPIOs. -.. image:: img/gd32f407v_start.jpg +.. image:: img/gd32f407v_start.webp :align: center :alt: gd32f407v_start diff --git a/boards/arm/gd32f450i_eval/Kconfig b/boards/arm/gd32f450i_eval/Kconfig deleted file mode 100644 index ec5800eae978d75..000000000000000 --- a/boards/arm/gd32f450i_eval/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2021 Teslabs Engineering S.L. -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_INIT_PRIORITY - int "Board initialization priority" - default 50 - help - Board initialization priority. diff --git a/boards/arm/gd32f450i_eval/doc/img/gd32f450i_eval.jpg b/boards/arm/gd32f450i_eval/doc/img/gd32f450i_eval.jpg deleted file mode 100644 index 032905d9842a827..000000000000000 Binary files a/boards/arm/gd32f450i_eval/doc/img/gd32f450i_eval.jpg and /dev/null differ diff --git a/boards/arm/gd32f450i_eval/doc/img/gd32f450i_eval.webp b/boards/arm/gd32f450i_eval/doc/img/gd32f450i_eval.webp new file mode 100644 index 000000000000000..2721d8bffbd31b7 Binary files /dev/null and b/boards/arm/gd32f450i_eval/doc/img/gd32f450i_eval.webp differ diff --git a/boards/arm/gd32f450i_eval/doc/index.rst b/boards/arm/gd32f450i_eval/doc/index.rst index 56017e4aef52bb0..59e9d258975cbdd 100644 --- a/boards/arm/gd32f450i_eval/doc/index.rst +++ b/boards/arm/gd32f450i_eval/doc/index.rst @@ -13,7 +13,7 @@ The GD32F450IK features a single-core ARM Cortex-M4F MCU which can run up to 200 MHz with flash accesses zero wait states, 3072kiB of Flash, 256kiB of SRAM and 140 GPIOs. -.. image:: img/gd32f450i_eval.jpg +.. image:: img/gd32f450i_eval.webp :align: center :alt: gd32f450i_eval diff --git a/boards/arm/gd32f450v_start/doc/img/gd32f450v_start.jpg b/boards/arm/gd32f450v_start/doc/img/gd32f450v_start.jpg deleted file mode 100644 index f2b3f48fbcab2cb..000000000000000 Binary files a/boards/arm/gd32f450v_start/doc/img/gd32f450v_start.jpg and /dev/null differ diff --git a/boards/arm/gd32f450v_start/doc/img/gd32f450v_start.webp b/boards/arm/gd32f450v_start/doc/img/gd32f450v_start.webp new file mode 100644 index 000000000000000..f76c58206b30c0c Binary files /dev/null and b/boards/arm/gd32f450v_start/doc/img/gd32f450v_start.webp differ diff --git a/boards/arm/gd32f450v_start/doc/index.rst b/boards/arm/gd32f450v_start/doc/index.rst index d3166c8ab640437..e45f05a58a65c4e 100644 --- a/boards/arm/gd32f450v_start/doc/index.rst +++ b/boards/arm/gd32f450v_start/doc/index.rst @@ -13,7 +13,7 @@ The GD32F450VK features a single-core ARM Cortex-M4F MCU which can run up to 200 MHz with flash accesses zero wait states, 3072kiB of Flash, 256kiB of SRAM and 82 GPIOs. -.. image:: img/gd32f450v_start.jpg +.. image:: img/gd32f450v_start.webp :align: center :alt: gd32f450v_start diff --git a/boards/arm/gd32f450z_eval/doc/img/gd32f450z_eval.jpg b/boards/arm/gd32f450z_eval/doc/img/gd32f450z_eval.jpg deleted file mode 100644 index 7fca77536466f79..000000000000000 Binary files a/boards/arm/gd32f450z_eval/doc/img/gd32f450z_eval.jpg and /dev/null differ diff --git a/boards/arm/gd32f450z_eval/doc/img/gd32f450z_eval.webp b/boards/arm/gd32f450z_eval/doc/img/gd32f450z_eval.webp new file mode 100644 index 000000000000000..be33bd01263e67e Binary files /dev/null and b/boards/arm/gd32f450z_eval/doc/img/gd32f450z_eval.webp differ diff --git a/boards/arm/gd32f450z_eval/doc/index.rst b/boards/arm/gd32f450z_eval/doc/index.rst index 179886cd0db4c16..0e31f262db3c6e9 100644 --- a/boards/arm/gd32f450z_eval/doc/index.rst +++ b/boards/arm/gd32f450z_eval/doc/index.rst @@ -13,7 +13,7 @@ The GD32F450ZK features a single-core ARM Cortex-M4F MCU which can run up to 200 MHz with flash accesses zero wait states, 3072kiB of Flash, 256kiB of SRAM and 114 GPIOs. -.. image:: img/gd32f450z_eval.jpg +.. image:: img/gd32f450z_eval.webp :align: center :alt: gd32f450z_eval diff --git a/boards/arm/google_dragonclaw/google_dragonclaw.dts b/boards/arm/google_dragonclaw/google_dragonclaw.dts index 2f17124747d339f..579adf4026f35d9 100644 --- a/boards/arm/google_dragonclaw/google_dragonclaw.dts +++ b/boards/arm/google_dragonclaw/google_dragonclaw.dts @@ -37,6 +37,7 @@ mul-n = <192>; /* 16MHz * 192/8 = 384MHz VCO clock */ div-p = <4>; /* 96MHz PLL general clock output */ div-q = <8>; /* 48MHz PLL output for USB, SDIO, RNG */ + div-r = <7>; /* I2S - lowest possible frequency to save power */ clocks = <&clk_hsi>; status = "okay"; }; diff --git a/boards/arm/lora_e5_mini/Kconfig.board b/boards/arm/lora_e5_mini/Kconfig.board new file mode 100644 index 000000000000000..1b4e30a54c4fa37 --- /dev/null +++ b/boards/arm/lora_e5_mini/Kconfig.board @@ -0,0 +1,8 @@ +# LoRa-E5 mini configuration + +# Copyright (c) 2023 Marcin Niestroj +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_LORA_E5_MINI + bool "LoRa E5 mini" + depends on SOC_STM32WLE5XX diff --git a/boards/arm/lora_e5_mini/Kconfig.defconfig b/boards/arm/lora_e5_mini/Kconfig.defconfig new file mode 100644 index 000000000000000..ca35c4321a09796 --- /dev/null +++ b/boards/arm/lora_e5_mini/Kconfig.defconfig @@ -0,0 +1,11 @@ +# LoRa-E5 mini configuration + +# Copyright (c) 2023 Marcin Niestroj +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_LORA_E5_MINI + +config BOARD + default "lora_e5_mini" + +endif # BOARD_LORA_E5_MINI diff --git a/boards/arm/lora_e5_mini/board.cmake b/boards/arm/lora_e5_mini/board.cmake new file mode 100644 index 000000000000000..ac24f811559b67d --- /dev/null +++ b/boards/arm/lora_e5_mini/board.cmake @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(pyocd "--target=stm32wle5jcix") +board_runner_args(pyocd "--flash-opt=-O reset_type=hw") +board_runner_args(pyocd "--flash-opt=-O connect_mode=under-reset") +board_runner_args(jlink "--device=STM32WLE5JC" "--speed=4000" "--reset-after-load") +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +board_runner_args(blackmagicprobe "--connect-rst") + +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake) diff --git a/boards/arm/lora_e5_mini/doc/img/lora_e5_mini.jpg b/boards/arm/lora_e5_mini/doc/img/lora_e5_mini.jpg new file mode 100644 index 000000000000000..8b22ba96ea6b636 Binary files /dev/null and b/boards/arm/lora_e5_mini/doc/img/lora_e5_mini.jpg differ diff --git a/boards/arm/lora_e5_mini/doc/img/lora_e5_mini_pinout.jpg b/boards/arm/lora_e5_mini/doc/img/lora_e5_mini_pinout.jpg new file mode 100644 index 000000000000000..2cc0f5e17eb3f2c Binary files /dev/null and b/boards/arm/lora_e5_mini/doc/img/lora_e5_mini_pinout.jpg differ diff --git a/boards/arm/lora_e5_mini/doc/index.rst b/boards/arm/lora_e5_mini/doc/index.rst new file mode 100644 index 000000000000000..6e6be186dd773e1 --- /dev/null +++ b/boards/arm/lora_e5_mini/doc/index.rst @@ -0,0 +1,226 @@ +.. _lora_e5_mini: + +Seeed Studio LoRa-E5 mini +######################### + +Overview +******** + +LoRa-E5 mini is a compacted-sized development board suitable for the rapid +testing and building of small-sized LoRa device, exposing all capabilities of +Seeed Studio LoRa-E5 STM32WLE5JC module. + +.. image:: img/lora_e5_mini.jpg + :align: center + :alt: LoRa-E5 mini + +Hardware +******** + +The boards' LoRa-E5 Module packages a STM32WLE5JC SOC, a 32MHz TCXO, +and a 32.768kHz crystal oscillator in a 28-pin SMD package. +This STM32WLEJC SOC is powered by ARM Cortex-M4 core and integrates Semtech +SX126X LoRa IP to support (G)FSK, BPSK, (G)MSK, and LoRa modulations. + +- LoRa-E5 STM32WLE5JC Module with STM32WLE5JC multiprotocol LPWAN single-core + 32-bit microcontroller (Arm® Cortex®-M4 at 48 MHz) in 28-pin SMD package + featuring: + + - Ultra-low-power MCU + - RF transceiver (150 MHz to 960 MHz frequency range) supporting LoRa®, + (G)FSK, (G)MSK, and BPSK modulations + - 256-Kbyte Flash memory and 64-Kbyte SRAM + - Hardware encryption AES256-bit and a True random number generator + +- 1 user LED +- 2 serial communication (RX/TX) LEDs +- 1 boot/user and 1 reset push-button +- 32.768 kHz LSE crystal oscillator +- 32 MHz HSE oscillator +- Board connectors: + + - USB Type-C connector + - +/- (battery) power input pins (3-5V) + - SMA-K and IPEX antenna connectors + +- Delivered with SMA antenna (per default IPEX connector is disconnected) +- Flexible power-supply options: USB Type C or 3-5V battery soldered to +/- pins +- Suitable for rapid prototyping of end nodes based on LoRaWAN, Sigfox, wM-Bus, + and many other proprietary protocols +- All GPIOs led out from the LoRa-E5 STM32WLE5JC module +- 4x M2 mounting holes + +More information about the board can be found at the `LoRa-E5 mini Wiki`_. + +More information about LoRa-E5 STM32WLE5JC Module can be found here: + +- `LoRa-E5 STM32WLE5JC Module Wiki`_ +- `LoRa-E5 STM32WLE5JC Module datasheet`_ +- `STM32WLE5JC datasheet`_ +- `STM32WLE5JC reference manual`_ +- `STM32WLE5JC on www.st.com`_ + +Supported Features +================== + +The Zephyr LoRa-E5 mini configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| ADC | on-chip | adc | ++-----------+------------+-------------------------------------+ +| AES | on-chip | crypto | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtc | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| RADIO | on-chip | LoRa | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | independent watchdog | ++-----------+------------+-------------------------------------+ + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig and dts files: + +- :zephyr_file:`boards/arm/lora_e5_mini/lora_e5_mini_defconfig` +- :zephyr_file:`boards/arm/lora_e5_mini/lora_e5_mini.dts` + + +Connections and IOs +=================== + +LoRa-E5 mini has 4 GPIO controllers. These controllers are responsible for pin +muxing, input/output, pull-up, etc. + +Available pins: +--------------- + +.. image:: img/lora_e5_mini_pinout.jpg + :align: center + :alt: LoRa-E5 mini Pinout + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- USART_1 TX : PB6 +- USART_1 RX : PB7 +- I2C_2_SCL : PB15 +- I2C_2_SDA : PA15 +- BOOT_PB : PB13 +- LED_1 : PB5 + +System Clock +------------ + +LoRa-E5 mini board System Clock could be driven by the low-power internal (MSI), +High-speed internal (HSI) or High-speed external (HSE) oscillator, as well as +main PLL clock. By default System clock is driven by the MSI clock at 48MHz. + +Programming and Debugging +************************* + +Applications for the ``lora_e5_mini`` board configuration can be built the +usual way (see :ref:`build_an_application`). + +In the factory the module is flashed with an DFU bootloader, an AT command +firmware, and the read protection level 1 is enabled. +So before you can program a Zephyr application to the module for the first time +you have to reset the read protection to level 0. +In case you use an st-link debugger you can use the STM32CubeProgrammer GUI to +set the RDP option byte to ``AA``, +or use the STM32_Programmer_CLI passing the ``--readunprotect`` command +to perform this read protection regression. +The RDP level 1 to RDP level 0 regression will erase the factory programmed AT +firmware, from which seeed has neither released the source code nor a binary. +Also, note that on the module the ``BOOT0`` pin of the SOC is not accessible, +so the system bootloader will only be executed if configured in the option bytes. + +Flashing +======== + +The LoRa-E5 mini does not include a on-board debug probe. +But the module can be debugged by connecting an external debug probe to the +2.54mm header. +Depending on the external probe used, ``openocd``, the ``stm32cubeprogrammer``, +``pyocd``, ``blackmagic``, or ``jlink`` runner can be used to flash the board. +Additional notes: + +- Pyocd: For STM32WL support Pyocd needs additional target information, which + can be installed by adding "pack" support with the following pyocd command: + +.. code-block:: console + + $ pyocd pack --update + $ pyocd pack --install stm32wl + +Flashing an application to LoRa-E5 mini +--------------------------------------- + +Connect the LoRa-E5 to your host computer using the external debug probe. +Then build and flash an application. Here is an example for the +:ref:`hello_world` application. + +Run a serial host program to connect with your board: +Per default the console on ``usart1`` is available on the USB Type C connector +via the built-in USB to UART converter. + +.. code-block:: console + + $ picocom --baud 115200 /dev/ttyACM0 + +Then build and flash the application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: lora_e5_mini + :goals: build flash + +Debugging +========= + +You can debug an application in the usual way. Here is an example for the +:zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: lora_e5_mini + :maybe-skip-config: + :goals: debug + +.. _LoRa-E5 mini Wiki: + https://wiki.seeedstudio.com/LoRa_E5_mini/ + +.. _LoRa-E5 STM32WLE5JC Module Wiki: + https://wiki.seeedstudio.com/LoRa-E5_STM32WLE5JC_Module/ + +.. _LoRa-E5 STM32WLE5JC Module datasheet: + https://files.seeedstudio.com/products/317990687/res/LoRa-E5%20module%20datasheet_V1.0.pdf + +.. _STM32WLE5JC on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32wle5jc.html + +.. _STM32WLE5JC datasheet: + https://www.st.com/resource/en/datasheet/stm32wle5jc.pdf + +.. _STM32WLE5JC reference manual: + https://www.st.com/resource/en/reference_manual/dm00530369-stm32wlex-advanced-armbased-32bit-mcus-with-subghz-radio-solution-stmicroelectronics.pdf diff --git a/boards/arm/lora_e5_mini/lora_e5_mini.dts b/boards/arm/lora_e5_mini/lora_e5_mini.dts new file mode 100644 index 000000000000000..e65572c6e35066b --- /dev/null +++ b/boards/arm/lora_e5_mini/lora_e5_mini.dts @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include + +/ { + model = "Seeed Studio LoRa-E5 mini"; + compatible = "seeed,lora-e5-mini"; + + chosen { + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + leds { + compatible = "gpio-leds"; + red_led_1: led_1 { + gpios = <&gpiob 5 GPIO_ACTIVE_LOW>; + label = "User LED1"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + boot_button: button_0 { + label = "SW1"; + gpios = <&gpiob 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &red_led_1; + sw0 = &boot_button; + lora0 = &lora; + watchdog0 = &iwdg; + }; +}; + +stm32_lp_tick_source: &lptim1 { + status = "okay"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x80000000>, + <&rcc STM32_SRC_LSI LPTIM1_SEL(1)>; +}; + +&clk_lsi { + status = "okay"; +}; + +&clk_msi { + status = "okay"; + msi-range = <11>; +}; + +&rcc { + clocks = <&clk_msi>; + clock-frequency = ; + cpu1-prescaler = <1>; + ahb3-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pb6 &usart1_rx_pb7>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_scl_pb15 &i2c2_sda_pa15>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>, + <&rcc STM32_SRC_LSI RTC_SEL(2)>; + status = "okay"; +}; + +&iwdg { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(48)>; + }; + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000c000 DT_SIZE_K(96)>; + }; + slot1_partition: partition@24000 { + label = "image-1"; + reg = <0x00024000 DT_SIZE_K(96)>; + }; + + /* 16KB (8x2kB pages) of storage at the end of the flash */ + storage_partition: partition@3c000 { + label = "storage"; + reg = <0x0003c000 DT_SIZE_K(16)>; + }; + }; +}; diff --git a/boards/arm/lora_e5_mini/lora_e5_mini.yaml b/boards/arm/lora_e5_mini/lora_e5_mini.yaml new file mode 100644 index 000000000000000..144ee2275ad366b --- /dev/null +++ b/boards/arm/lora_e5_mini/lora_e5_mini.yaml @@ -0,0 +1,19 @@ +identifier: lora_e5_mini +name: Seeedstudio LoRa-E5 mini +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 64 +flash: 256 +supported: + - counter + - gpio + - i2c + - nvs + - uart + - watchdog + - lora +vendor: seeed diff --git a/boards/arm/lora_e5_mini/lora_e5_mini_defconfig b/boards/arm/lora_e5_mini/lora_e5_mini_defconfig new file mode 100644 index 000000000000000..5e6649fe25ac060 --- /dev/null +++ b/boards/arm/lora_e5_mini/lora_e5_mini_defconfig @@ -0,0 +1,24 @@ +CONFIG_SOC_SERIES_STM32WLX=y +CONFIG_SOC_STM32WLE5XX=y + +# enable uart driver +CONFIG_SERIAL=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable Clocks +CONFIG_CLOCK_CONTROL=y + +# console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/arm/lora_e5_mini/support/openocd.cfg b/boards/arm/lora_e5_mini/support/openocd.cfg new file mode 100644 index 000000000000000..f4902698c6358b3 --- /dev/null +++ b/boards/arm/lora_e5_mini/support/openocd.cfg @@ -0,0 +1,7 @@ +source [find interface/stlink.cfg] + +transport select hla_swd + +source [find target/stm32wlx.cfg] + +reset_config srst_only diff --git a/boards/arm/lpcxpresso11u68/lpcxpresso11u68.yaml b/boards/arm/lpcxpresso11u68/lpcxpresso11u68.yaml index e59360c084b1401..192ca797f629054 100644 --- a/boards/arm/lpcxpresso11u68/lpcxpresso11u68.yaml +++ b/boards/arm/lpcxpresso11u68/lpcxpresso11u68.yaml @@ -2,6 +2,8 @@ identifier: lpcxpresso11u68 name: NXP LPCxpresso 11U68 type: mcu arch: arm +ram: 32 +flash: 256 toolchain: - zephyr supported: diff --git a/boards/arm/lpcxpresso55s06/Kconfig.defconfig b/boards/arm/lpcxpresso55s06/Kconfig.defconfig index 57d53c1489ac6c4..48340c5f589f4c4 100644 --- a/boards/arm/lpcxpresso55s06/Kconfig.defconfig +++ b/boards/arm/lpcxpresso55s06/Kconfig.defconfig @@ -8,4 +8,11 @@ if BOARD_LPCXPRESSO55S06 config BOARD default "lpcxpresso55s06" +if BOOTLOADER_MCUBOOT +choice MCUBOOT_BOOTLOADER_MODE + # Board only supports MCUBoot via "upgrade only" method: + default MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY +endchoice +endif #BOOTLOADER_MCUBOOT + endif # BOARD_LPCXPRESSO55S06 diff --git a/boards/arm/lpcxpresso55s16/Kconfig.defconfig b/boards/arm/lpcxpresso55s16/Kconfig.defconfig index 49ed6830ed2e6c4..2979ac8808d73f6 100644 --- a/boards/arm/lpcxpresso55s16/Kconfig.defconfig +++ b/boards/arm/lpcxpresso55s16/Kconfig.defconfig @@ -12,4 +12,11 @@ config FXOS8700_DRDY_INT1 default y depends on FXOS8700_TRIGGER +if BOOTLOADER_MCUBOOT +choice MCUBOOT_BOOTLOADER_MODE + # Board only supports MCUBoot via "upgrade only" method: + default MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY +endchoice +endif #BOOTLOADER_MCUBOOT + endif # BOARD_LPCXPRESSO55S16 diff --git a/boards/arm/lpcxpresso55s28/Kconfig.defconfig b/boards/arm/lpcxpresso55s28/Kconfig.defconfig index 40e95c1b388f84e..ee3fd9685c41e1a 100644 --- a/boards/arm/lpcxpresso55s28/Kconfig.defconfig +++ b/boards/arm/lpcxpresso55s28/Kconfig.defconfig @@ -37,4 +37,11 @@ config FLASH_LOAD_SIZE default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) depends on BOARD_LPCXPRESSO55S28 && TRUSTED_EXECUTION_SECURE +if BOOTLOADER_MCUBOOT +choice MCUBOOT_BOOTLOADER_MODE + # Board only supports MCUBoot via "upgrade only" method: + default MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY +endchoice +endif #BOOTLOADER_MCUBOOT + endif # BOARD_LPCXPRESSO55S28 diff --git a/boards/arm/lpcxpresso55s36/Kconfig.defconfig b/boards/arm/lpcxpresso55s36/Kconfig.defconfig index 3f3b1305bf79686..fd3ea5cd189ea19 100644 --- a/boards/arm/lpcxpresso55s36/Kconfig.defconfig +++ b/boards/arm/lpcxpresso55s36/Kconfig.defconfig @@ -8,4 +8,11 @@ if BOARD_LPCXPRESSO55S36 config BOARD default "lpcxpresso55s36" +if BOOTLOADER_MCUBOOT +choice MCUBOOT_BOOTLOADER_MODE + # Board only supports MCUBoot via "upgrade only" method: + default MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY +endchoice +endif #BOOTLOADER_MCUBOOT + endif # BOARD_LPCXPRESSO55S36 diff --git a/boards/arm/lpcxpresso55s69/Kconfig.defconfig b/boards/arm/lpcxpresso55s69/Kconfig.defconfig index 7c98507e35c38f2..c8bc5421e098feb 100644 --- a/boards/arm/lpcxpresso55s69/Kconfig.defconfig +++ b/boards/arm/lpcxpresso55s69/Kconfig.defconfig @@ -55,4 +55,11 @@ choice TFM_PROFILE_TYPE default TFM_PROFILE_TYPE_MEDIUM endchoice +if BOOTLOADER_MCUBOOT +choice MCUBOOT_BOOTLOADER_MODE + # Board only supports MCUBoot via "upgrade only" method: + default MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY +endchoice +endif #BOOTLOADER_MCUBOOT + endif # BOARD_LPCXPRESSO55S69_CPU0 || BOARD_LPCXPRESSO55S69_CPU1 diff --git a/boards/arm/lpcxpresso55s69/doc/index.rst b/boards/arm/lpcxpresso55s69/doc/index.rst index 408cd18aa91f511..d6c16095f5380fc 100644 --- a/boards/arm/lpcxpresso55s69/doc/index.rst +++ b/boards/arm/lpcxpresso55s69/doc/index.rst @@ -256,7 +256,7 @@ Dual Core samples System Clock ============ -The LPC55S69 SoC is configured to use PLL1 clocked from the external 24MHz +The LPC55S69 SoC is configured to use PLL1 clocked from the external 16MHz crystal, running at 144MHz as a source for the system clock. When the flash controller is enabled, the core clock will be reduced to 96MHz. The application may reconfigure clocks after initialization, provided that the core clock is diff --git a/boards/arm/mimx8mm_evk/mimx8mm_evk.yaml b/boards/arm/mimx8mm_evk/mimx8mm_evk.yaml index 8854d16ac551719..4c1779778ba7998 100644 --- a/boards/arm/mimx8mm_evk/mimx8mm_evk.yaml +++ b/boards/arm/mimx8mm_evk/mimx8mm_evk.yaml @@ -8,8 +8,8 @@ identifier: mimx8mm_evk name: NXP i.MX8M Mini EVK type: mcu arch: arm -ram: 32 -flash: 32 +ram: 128 +flash: 128 toolchain: - zephyr - gnuarmemb diff --git a/boards/arm/mimx8mm_phyboard_polis/mimx8mm_phyboard_polis.yaml b/boards/arm/mimx8mm_phyboard_polis/mimx8mm_phyboard_polis.yaml index ee0fd50bf5feb15..399336291f933ea 100644 --- a/boards/arm/mimx8mm_phyboard_polis/mimx8mm_phyboard_polis.yaml +++ b/boards/arm/mimx8mm_phyboard_polis/mimx8mm_phyboard_polis.yaml @@ -8,8 +8,8 @@ identifier: mimx8mm_phyboard_polis name: Phyboard Polis i.MX8M Mini type: mcu arch: arm -ram: 32 -flash: 32 +ram: 128 +flash: 128 toolchain: - zephyr - gnuarmemb diff --git a/boards/arm/mimx8mq_evk/mimx8mq_evk_cm4.yaml b/boards/arm/mimx8mq_evk/mimx8mq_evk_cm4.yaml index 580b8cef0f38b17..f5fee9cea2fc9dc 100644 --- a/boards/arm/mimx8mq_evk/mimx8mq_evk_cm4.yaml +++ b/boards/arm/mimx8mq_evk/mimx8mq_evk_cm4.yaml @@ -8,8 +8,8 @@ identifier: mimx8mq_evk_cm4 name: NXP i.MX8MQ EVK CM4 type: mcu arch: arm -ram: 32 -flash: 32 +ram: 128 +flash: 128 toolchain: - zephyr - gnuarmemb diff --git a/boards/arm/mimxrt1010_evk/mimxrt1010_evk.yaml b/boards/arm/mimxrt1010_evk/mimxrt1010_evk.yaml index 302b3c64d80d41f..e611af6c798531d 100644 --- a/boards/arm/mimxrt1010_evk/mimxrt1010_evk.yaml +++ b/boards/arm/mimxrt1010_evk/mimxrt1010_evk.yaml @@ -13,7 +13,7 @@ toolchain: - zephyr - gnuarmemb - xtools -ram: 32 +ram: 64 flash: 16384 supported: - arduino_gpio diff --git a/boards/arm/mimxrt1040_evk/board.cmake b/boards/arm/mimxrt1040_evk/board.cmake index 54d459f5c0825c6..10e09bc14052662 100644 --- a/boards/arm/mimxrt1040_evk/board.cmake +++ b/boards/arm/mimxrt1040_evk/board.cmake @@ -5,5 +5,9 @@ # board_runner_args(jlink "--device=MIMXRT1042XXX6B") +board_runner_args(linkserver "--device=MIMXRT1042xxxxB:MIMXRT1040-EVK") +board_runner_args(pyocd "--target=MIMXRT1042XJM5B") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/arm/mimxrt685_evk/board.cmake b/boards/arm/mimxrt685_evk/board.cmake index a399d5f6398e230..79e6f768dd1d097 100644 --- a/boards/arm/mimxrt685_evk/board.cmake +++ b/boards/arm/mimxrt685_evk/board.cmake @@ -5,5 +5,7 @@ # board_runner_args(jlink "--device=MIMXRT685S_M33" "--reset-after-load") +board_runner_args(linkserver "--device=MIMXRT685S:EVK-MIMXRT685") +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/mimxrt685_evk/doc/index.rst b/boards/arm/mimxrt685_evk/doc/index.rst index f0236e3a64f4e66..579cd1e4087d112 100644 --- a/boards/arm/mimxrt685_evk/doc/index.rst +++ b/boards/arm/mimxrt685_evk/doc/index.rst @@ -227,6 +227,20 @@ configured by default to use the LPC-Link2. .. tabs:: + .. group-tab:: LinkServer CMSIS-DAP + + 1. Install the :ref:`linkserver-debug-host-tools` and make sure they are in your + search path. LinkServer works with the default CMSIS-DAP firmware included in + the on-board debugger. + 2. Make sure the jumpers JP17, JP18 and JP19 are installed. + + linkserver is the default runner for this board + + .. code-block:: console + + west flash + west debug + .. group-tab:: LPCLink2 JLink Onboard @@ -236,6 +250,11 @@ configured by default to use the LPC-Link2. 3. Follow the instructions in :ref:`lpclink2-jlink-onboard-debug-probe` to program the J-Link firmware. Please make sure you have the latest firmware for this board. + .. code-block:: console + + west flash -r jlink + west debug -r jlink + .. group-tab:: JLink External @@ -248,6 +267,11 @@ configured by default to use the LPC-Link2. See :ref:`jlink-external-debug-probe` for more information. + .. code-block:: console + + west flash -r jlink + west debug -r jlink + Configuring a Console ===================== @@ -263,7 +287,7 @@ Flashing ======== Here is an example for the :ref:`hello_world` application. This example uses the -:ref:`jlink-debug-host-tools` as default. +:ref:`linkserver-debug-host-tools` as default. .. zephyr-app-commands:: :zephyr-app: samples/hello_world @@ -282,7 +306,7 @@ Debugging ========= Here is an example for the :ref:`hello_world` application. This example uses the -:ref:`jlink-debug-host-tools` as default. +:ref:`linkserver-debug-host-tools` as default. .. zephyr-app-commands:: :zephyr-app: samples/hello_world diff --git a/boards/arm/mps2_an385/doc/index.rst b/boards/arm/mps2_an385/doc/index.rst index 1f9d1a59e23827d..ac27e70e5938193 100644 --- a/boards/arm/mps2_an385/doc/index.rst +++ b/boards/arm/mps2_an385/doc/index.rst @@ -226,7 +226,7 @@ Peripheral Mapping: - I2C_4_SDA : D40 - I2C_4_SCL : D41 -For mode details please refer to `MPS2 Technical Reference Manual (TRM)`_. +For more details please refer to `MPS2 Technical Reference Manual (TRM)`_. System Clock ============ diff --git a/boards/arm/mps2_an521/doc/index.rst b/boards/arm/mps2_an521/doc/index.rst index 1cd049ec8f96e29..e8789e72e18d501 100644 --- a/boards/arm/mps2_an521/doc/index.rst +++ b/boards/arm/mps2_an521/doc/index.rst @@ -331,7 +331,7 @@ Peripheral Mapping: - I2C_4_SDA : D40 - I2C_4_SCL : D41 -For mode details refer to `MPS2+ AN521 Technical Reference Manual (TRM)`_. +For more details refer to `MPS2+ AN521 Technical Reference Manual (TRM)`_. LED ============ diff --git a/boards/arm/mps3_an547/doc/index.rst b/boards/arm/mps3_an547/doc/index.rst index 002c4210f5266fa..b5f383d546a07ce 100644 --- a/boards/arm/mps3_an547/doc/index.rst +++ b/boards/arm/mps3_an547/doc/index.rst @@ -111,7 +111,7 @@ features. The default configuration can be found in the defconfig file: ``boards/arm/mps3_an547/mps3_an547_defconfig``. -For mode details refer to `MPS3 AN547 Technical Reference Manual (TRM)`_. +For more details refer to `MPS3 AN547 Technical Reference Manual (TRM)`_. Serial Port =========== diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_cpunet_reset.c b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_cpunet_reset.c index 4368ca303fc17b5..f9082e6ca4006d2 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_cpunet_reset.c +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_cpunet_reset.c @@ -10,8 +10,7 @@ #include #include - -#include +#include LOG_MODULE_REGISTER(nrf5340_audio_dk_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -25,11 +24,11 @@ static int core_config(void) { nrf_gpiote_latency_t latency; - latency = nrfx_gpiote_latency_get(); + latency = nrf_gpiote_latency_get(NRF_GPIOTE); if (latency != NRF_GPIOTE_LATENCY_LOWPOWER) { LOG_DBG("Setting gpiote latency to low power"); - nrfx_gpiote_latency_set(NRF_GPIOTE_LATENCY_LOWPOWER); + nrf_gpiote_latency_set(NRF_GPIOTE, NRF_GPIOTE_LATENCY_LOWPOWER); } return 0; diff --git a/boards/arm/nucleo_c031c6/doc/index.rst b/boards/arm/nucleo_c031c6/doc/index.rst index fcf134f497e4d35..3e28230cba2d778 100644 --- a/boards/arm/nucleo_c031c6/doc/index.rst +++ b/boards/arm/nucleo_c031c6/doc/index.rst @@ -110,7 +110,7 @@ Default Zephyr Peripheral Mapping: - UART_2 TX/RX : PA2/PA3 (ST-Link Virtual Port Com) - LD4 : PA5 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_f030r8/doc/index.rst b/boards/arm/nucleo_f030r8/doc/index.rst index 821470b20c048f9..a6f104398c75e4d 100644 --- a/boards/arm/nucleo_f030r8/doc/index.rst +++ b/boards/arm/nucleo_f030r8/doc/index.rst @@ -129,7 +129,7 @@ Default Zephyr Peripheral Mapping: - ADC : PA0 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_f031k6/doc/index.rst b/boards/arm/nucleo_f031k6/doc/index.rst index b7adddf65093836..ccfb1540f26f3b4 100644 --- a/boards/arm/nucleo_f031k6/doc/index.rst +++ b/boards/arm/nucleo_f031k6/doc/index.rst @@ -98,7 +98,7 @@ Default Zephyr Peripheral Mapping: - LD2 : PB3 -For mode details please refer to `STM32 Nucleo-32 board User Manual`_. +For more details please refer to `STM32 Nucleo-32 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_f042k6/doc/index.rst b/boards/arm/nucleo_f042k6/doc/index.rst index a9676350eb4c5f5..66ad80adeedc051 100644 --- a/boards/arm/nucleo_f042k6/doc/index.rst +++ b/boards/arm/nucleo_f042k6/doc/index.rst @@ -98,7 +98,7 @@ Default Zephyr Peripheral Mapping: - LD2 : PB3 -For mode details please refer to `STM32 Nucleo-32 board User Manual`_. +For more details please refer to `STM32 Nucleo-32 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_f070rb/doc/index.rst b/boards/arm/nucleo_f070rb/doc/index.rst index 5d7e214bd1bc28c..50a96e3fed4a214 100644 --- a/boards/arm/nucleo_f070rb/doc/index.rst +++ b/boards/arm/nucleo_f070rb/doc/index.rst @@ -126,7 +126,7 @@ Default Zephyr Peripheral Mapping: - USER_PB : PC13 - LD1 : PA5 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_f091rc/doc/index.rst b/boards/arm/nucleo_f091rc/doc/index.rst index f1f0df58e1083e6..9ff09e28770bb14 100644 --- a/boards/arm/nucleo_f091rc/doc/index.rst +++ b/boards/arm/nucleo_f091rc/doc/index.rst @@ -143,7 +143,7 @@ Default Zephyr Peripheral Mapping: - DAC_OUT1 : PA4 - PWM_2_CH1 : PA5 (might conflict with SPI1) -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_f103rb/doc/index.rst b/boards/arm/nucleo_f103rb/doc/index.rst index b717c75b58a59e8..8f67b04ad626495 100644 --- a/boards/arm/nucleo_f103rb/doc/index.rst +++ b/boards/arm/nucleo_f103rb/doc/index.rst @@ -133,7 +133,7 @@ Default Zephyr Peripheral Mapping: - USER_PB : PC13 - LD1 : PA5 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_f334r8/doc/index.rst b/boards/arm/nucleo_f334r8/doc/index.rst index d44ee9e51d733eb..64824e787ebab35 100644 --- a/boards/arm/nucleo_f334r8/doc/index.rst +++ b/boards/arm/nucleo_f334r8/doc/index.rst @@ -123,7 +123,7 @@ Default Zephyr Peripheral Mapping: - USER_PB : PC13 - LD2 : PA5 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_f401re/doc/index.rst b/boards/arm/nucleo_f401re/doc/index.rst index c844ef9ab9c58f6..aa01b1ad3ad4cb8 100644 --- a/boards/arm/nucleo_f401re/doc/index.rst +++ b/boards/arm/nucleo_f401re/doc/index.rst @@ -109,7 +109,7 @@ Available pins: :align: center :alt: Nucleo F401RE Morpho connectors -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_f410rb/doc/index.rst b/boards/arm/nucleo_f410rb/doc/index.rst index c5702552ca8a1f3..23c979e49aaa15d 100644 --- a/boards/arm/nucleo_f410rb/doc/index.rst +++ b/boards/arm/nucleo_f410rb/doc/index.rst @@ -120,7 +120,7 @@ Available pins: :align: center :alt: Nucleo F410RB Morpho connectors (top right) -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_f411re/doc/index.rst b/boards/arm/nucleo_f411re/doc/index.rst index ee7d652d1c55a17..908dfbf9a2a20b6 100644 --- a/boards/arm/nucleo_f411re/doc/index.rst +++ b/boards/arm/nucleo_f411re/doc/index.rst @@ -107,7 +107,7 @@ Available pins: :align: center :alt: Nucleo F411RE Morpho connectors -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_f413zh/doc/index.rst b/boards/arm/nucleo_f413zh/doc/index.rst index b00213ced7e74e2..7979171472e1c35 100644 --- a/boards/arm/nucleo_f413zh/doc/index.rst +++ b/boards/arm/nucleo_f413zh/doc/index.rst @@ -117,7 +117,7 @@ Available pins: :align: center :alt: Nucleo F413ZH Morpho connectors (right) -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_f429zi/doc/index.rst b/boards/arm/nucleo_f429zi/doc/index.rst index 3b20f6a7a0cfe7c..e65e9194ad4d7b1 100644 --- a/boards/arm/nucleo_f429zi/doc/index.rst +++ b/boards/arm/nucleo_f429zi/doc/index.rst @@ -139,7 +139,7 @@ Available pins: :align: center :alt: Nucleo F429ZI Morpho connectors (right) -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_f446re/doc/index.rst b/boards/arm/nucleo_f446re/doc/index.rst index a835d963d2b79f5..37d62c043107cf6 100644 --- a/boards/arm/nucleo_f446re/doc/index.rst +++ b/boards/arm/nucleo_f446re/doc/index.rst @@ -118,7 +118,7 @@ Available pins: :align: center :alt: Nucleo F446RE Morpho connectors (top right) -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_f446ze/doc/index.rst b/boards/arm/nucleo_f446ze/doc/index.rst index b0a8f4314623035..697324e84fab9cb 100644 --- a/boards/arm/nucleo_f446ze/doc/index.rst +++ b/boards/arm/nucleo_f446ze/doc/index.rst @@ -129,7 +129,7 @@ Available pins: :align: center :alt: Nucleo F446ZE Morpho connectors (right) -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_f746zg/doc/index.rst b/boards/arm/nucleo_f746zg/doc/index.rst index ef9fdf9d20e6d12..8bc083bcc3f6e58 100644 --- a/boards/arm/nucleo_f746zg/doc/index.rst +++ b/boards/arm/nucleo_f746zg/doc/index.rst @@ -128,7 +128,7 @@ Other hardware features are not yet supported on this Zephyr port. The default configuration can be found in the defconfig file: ``boards/arm/nucleo_f746zg/nucleo_f746zg_defconfig`` -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_f756zg/doc/index.rst b/boards/arm/nucleo_f756zg/doc/index.rst index 2616a3b6dccc3fb..aa13ddb7f200906 100644 --- a/boards/arm/nucleo_f756zg/doc/index.rst +++ b/boards/arm/nucleo_f756zg/doc/index.rst @@ -118,7 +118,7 @@ Other hardware features are not yet supported on this Zephyr port. The default configuration can be found in the defconfig file: ``boards/arm/nucleo_f756zg/nucleo_f756zg_defconfig`` -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_f767zi/doc/index.rst b/boards/arm/nucleo_f767zi/doc/index.rst index bed503e2609c3f6..7eca2af1edaa196 100644 --- a/boards/arm/nucleo_f767zi/doc/index.rst +++ b/boards/arm/nucleo_f767zi/doc/index.rst @@ -135,7 +135,7 @@ Other hardware features are not yet supported on this Zephyr port. The default configuration can be found in the defconfig file: ``boards/arm/nucleo_f767zi/nucleo_f767zi_defconfig`` -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_g031k8/doc/index.rst b/boards/arm/nucleo_g031k8/doc/index.rst index 6f933b08546150b..93a10b553ab865c 100644 --- a/boards/arm/nucleo_g031k8/doc/index.rst +++ b/boards/arm/nucleo_g031k8/doc/index.rst @@ -105,7 +105,7 @@ Default Zephyr Peripheral Mapping: - SPI1 SCK/MISO/MOSI : PB3/PB4/PB5 (Arduino SPI) - LD3 : PC6 -For mode details please refer to `STM32 Nucleo-32 board User Manual`_. +For more details please refer to `STM32 Nucleo-32 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_g070rb/doc/index.rst b/boards/arm/nucleo_g070rb/doc/index.rst index 056bb298c4f43ff..8908ed5ce43c6e0 100644 --- a/boards/arm/nucleo_g070rb/doc/index.rst +++ b/boards/arm/nucleo_g070rb/doc/index.rst @@ -138,7 +138,7 @@ Default Zephyr Peripheral Mapping: - ADC1 IN1 : PA1 - DAC1_OUT1 : PA4 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_g071rb/doc/index.rst b/boards/arm/nucleo_g071rb/doc/index.rst index f6aebe8f12bb0c2..424f1ade9f77365 100644 --- a/boards/arm/nucleo_g071rb/doc/index.rst +++ b/boards/arm/nucleo_g071rb/doc/index.rst @@ -142,7 +142,7 @@ Default Zephyr Peripheral Mapping: - ADC1 IN1 : PA1 - DAC1_OUT1 : PA4 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_g0b1re/doc/index.rst b/boards/arm/nucleo_g0b1re/doc/index.rst index 0ad6085262763ef..7ca35bd75114334 100644 --- a/boards/arm/nucleo_g0b1re/doc/index.rst +++ b/boards/arm/nucleo_g0b1re/doc/index.rst @@ -138,7 +138,7 @@ Default Zephyr Peripheral Mapping: - ADC1 IN1 : PA1 - DAC1_OUT1 : PA4 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_g431rb/doc/index.rst b/boards/arm/nucleo_g431rb/doc/index.rst index 7d60b8c542600d2..0359a29b231e9f1 100644 --- a/boards/arm/nucleo_g431rb/doc/index.rst +++ b/boards/arm/nucleo_g431rb/doc/index.rst @@ -134,7 +134,7 @@ Connections and IOs Nucleo G431RB Board has 6 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32G4 Nucleo-64 board User Manual`_. +For more details please refer to `STM32G4 Nucleo-64 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_g474re/doc/index.rst b/boards/arm/nucleo_g474re/doc/index.rst index 437668ed42eb1da..6705e20fd78be9e 100644 --- a/boards/arm/nucleo_g474re/doc/index.rst +++ b/boards/arm/nucleo_g474re/doc/index.rst @@ -140,7 +140,7 @@ Connections and IOs Nucleo G474RE Board has 6 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32G4 Nucleo-64 board User Manual`_. +For more details please refer to `STM32G4 Nucleo-64 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_h563zi/doc/index.rst b/boards/arm/nucleo_h563zi/doc/index.rst index 9b6f880ac4c1753..7d1ac5c5b5aeae1 100644 --- a/boards/arm/nucleo_h563zi/doc/index.rst +++ b/boards/arm/nucleo_h563zi/doc/index.rst @@ -206,7 +206,7 @@ Connections and IOs Nucleo H563ZI Board has 9 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32H5 Nucleo-144 board User Manual`_. +For more details please refer to `STM32H5 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_h723zg/Kconfig.defconfig b/boards/arm/nucleo_h723zg/Kconfig.defconfig index 7b5c327e97d83b6..26f4491a7ad0672 100644 --- a/boards/arm/nucleo_h723zg/Kconfig.defconfig +++ b/boards/arm/nucleo_h723zg/Kconfig.defconfig @@ -15,4 +15,8 @@ config NET_L2_ETHERNET endif # NETWORKING +config USB_DC_HAS_HS_SUPPORT + default y + depends on USB_DC_STM32 + endif # BOARD_NUCLEO_H723ZG diff --git a/boards/arm/nucleo_h723zg/doc/index.rst b/boards/arm/nucleo_h723zg/doc/index.rst index 09b71835f67da93..44a87bb512930ac 100644 --- a/boards/arm/nucleo_h723zg/doc/index.rst +++ b/boards/arm/nucleo_h723zg/doc/index.rst @@ -121,7 +121,7 @@ Other hardware features are not yet supported on this Zephyr port. The default configuration per core can be found in the defconfig files: ``boards/arm/nucleo_h723zg/nucleo_h723zg_defconfig`` -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_h743zi/doc/index.rst b/boards/arm/nucleo_h743zi/doc/index.rst index c401e3ab098c744..e6cb6e242cddffb 100644 --- a/boards/arm/nucleo_h743zi/doc/index.rst +++ b/boards/arm/nucleo_h743zi/doc/index.rst @@ -135,7 +135,7 @@ Other hardware features are not yet supported on this Zephyr port. The default configuration can be found in the defconfig file: ``boards/arm/nucleo_h743zi/nucleo_h743zi_defconfig`` -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_h745zi_q/doc/index.rst b/boards/arm/nucleo_h745zi_q/doc/index.rst index 60f86f2ab8155fc..36c4b80bc58add2 100644 --- a/boards/arm/nucleo_h745zi_q/doc/index.rst +++ b/boards/arm/nucleo_h745zi_q/doc/index.rst @@ -122,7 +122,7 @@ The default configuration per core can be found in the defconfig files: ``boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m7_defconfig`` and ``boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m4_defconfig`` -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m7.dts b/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m7.dts index d63b4ff8a58edf6..184232867bb52a0 100644 --- a/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m7.dts +++ b/boards/arm/nucleo_h745zi_q/nucleo_h745zi_q_m7.dts @@ -6,7 +6,6 @@ /dts-v1/; #include -#include #include "nucleo_h745zi_q.dtsi" /* @@ -63,7 +62,7 @@ div-m = <1>; mul-n = <120>; div-p = <2>; - div-q = <2>; + div-q = <8>; div-r = <2>; clocks = <&clk_hse>; status = "okay"; diff --git a/boards/arm/nucleo_h753zi/doc/index.rst b/boards/arm/nucleo_h753zi/doc/index.rst index 058cbc67c9f4666..eab88c9952a7a4d 100644 --- a/boards/arm/nucleo_h753zi/doc/index.rst +++ b/boards/arm/nucleo_h753zi/doc/index.rst @@ -129,7 +129,7 @@ Other hardware features are not yet supported on this Zephyr port. The default configuration can be found in the defconfig file: ``boards/arm/nucleo_h753zi/nucleo_h753zi_defconfig`` -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_h7a3zi_q/Kconfig.defconfig b/boards/arm/nucleo_h7a3zi_q/Kconfig.defconfig index 922423e3669edc3..ec43ace7dcb5cf3 100644 --- a/boards/arm/nucleo_h7a3zi_q/Kconfig.defconfig +++ b/boards/arm/nucleo_h7a3zi_q/Kconfig.defconfig @@ -8,4 +8,8 @@ if BOARD_NUCLEO_H7A3ZI_Q config BOARD default "nucleo_h7a3zi_q" +config USB_DC_HAS_HS_SUPPORT + default y + depends on USB_DC_STM32 + endif # BOARD_NUCLEO_H7A3ZI_Q diff --git a/boards/arm/nucleo_h7a3zi_q/doc/index.rst b/boards/arm/nucleo_h7a3zi_q/doc/index.rst index 7b107733510f6a0..1144f13e731406f 100644 --- a/boards/arm/nucleo_h7a3zi_q/doc/index.rst +++ b/boards/arm/nucleo_h7a3zi_q/doc/index.rst @@ -117,7 +117,7 @@ Other hardware features are not yet supported on this Zephyr port. The default configuration can be found in the defconfig file: ``boards/arm/nucleo_h7a3zi_q/nucleo_h7a3zi_q_defconfig`` -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_l011k4/doc/index.rst b/boards/arm/nucleo_l011k4/doc/index.rst index 9b815ede4de2cf3..04fc12c53f32b46 100644 --- a/boards/arm/nucleo_l011k4/doc/index.rst +++ b/boards/arm/nucleo_l011k4/doc/index.rst @@ -113,7 +113,7 @@ Default Zephyr Peripheral Mapping: - SPI1 SCK/MISO/MOSI : PA5/PA6/PA7 (Arduino SPI) - LD2 : PB3 -For mode details please refer to `STM32 Nucleo-32 board User Manual`_. +For more details please refer to `STM32 Nucleo-32 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_l031k6/doc/index.rst b/boards/arm/nucleo_l031k6/doc/index.rst index eb1f6e253874ff4..da0fcaa271e3ced 100644 --- a/boards/arm/nucleo_l031k6/doc/index.rst +++ b/boards/arm/nucleo_l031k6/doc/index.rst @@ -106,7 +106,7 @@ Default Zephyr Peripheral Mapping: - SPI1 SCK/MISO/MOSI : PA5/PA6/PA7 (Arduino SPI) - LD2 : PB3 -For mode details please refer to `STM32 Nucleo-32 board User Manual`_. +For more details please refer to `STM32 Nucleo-32 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_l053r8/doc/index.rst b/boards/arm/nucleo_l053r8/doc/index.rst index 33f84b14e6cc018..ba448176fcad9b1 100644 --- a/boards/arm/nucleo_l053r8/doc/index.rst +++ b/boards/arm/nucleo_l053r8/doc/index.rst @@ -122,7 +122,7 @@ Default Zephyr Peripheral Mapping: - USER_PB : PC13 - LD2 : PA5 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_l073rz/doc/index.rst b/boards/arm/nucleo_l073rz/doc/index.rst index de662f5b14ff971..a828a5b70eb69d6 100644 --- a/boards/arm/nucleo_l073rz/doc/index.rst +++ b/boards/arm/nucleo_l073rz/doc/index.rst @@ -136,7 +136,7 @@ Default Zephyr Peripheral Mapping: - DAC : PA4 - PWM_2_CH1 : PA5 (might conflict with SPI1) -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_l152re/doc/index.rst b/boards/arm/nucleo_l152re/doc/index.rst index 2595144e730de99..020beb6583f4e0c 100644 --- a/boards/arm/nucleo_l152re/doc/index.rst +++ b/boards/arm/nucleo_l152re/doc/index.rst @@ -130,7 +130,7 @@ Default Zephyr Peripheral Mapping: - DAC : PA4 - PWM_3_CH1 : PA6 -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/nucleo_l412rb_p/doc/index.rst b/boards/arm/nucleo_l412rb_p/doc/index.rst index 007ae04379dc7f7..3485d01cba1d6fa 100644 --- a/boards/arm/nucleo_l412rb_p/doc/index.rst +++ b/boards/arm/nucleo_l412rb_p/doc/index.rst @@ -176,7 +176,7 @@ Available pins: :align: center :alt: Nucleo L412RB-P -For mode details please refer to `ST Nucleo L412RB-P User Manual`_. +For more details please refer to `ST Nucleo L412RB-P User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_l432kc/doc/index.rst b/boards/arm/nucleo_l432kc/doc/index.rst index 94d6f6f20f0ac6c..b054c472f22603a 100644 --- a/boards/arm/nucleo_l432kc/doc/index.rst +++ b/boards/arm/nucleo_l432kc/doc/index.rst @@ -137,7 +137,7 @@ Available pins: :align: center :alt: Nucleo L432KC Arduino connectors -For mode details please refer to `STM32 Nucleo-32 board User Manual`_. +For more details please refer to `STM32 Nucleo-32 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_l433rc_p/doc/index.rst b/boards/arm/nucleo_l433rc_p/doc/index.rst index da2660417c01f24..6e86a44cee0ccf6 100644 --- a/boards/arm/nucleo_l433rc_p/doc/index.rst +++ b/boards/arm/nucleo_l433rc_p/doc/index.rst @@ -140,7 +140,7 @@ Available pins: :align: center :alt: Nucleo L433RC-P -For mode details please refer to `ST Nucleo L433RC-P User Manual`_. +For more details please refer to `ST Nucleo L433RC-P User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_l476rg/doc/index.rst b/boards/arm/nucleo_l476rg/doc/index.rst index cfbf949df57b5eb..10dff333643841e 100644 --- a/boards/arm/nucleo_l476rg/doc/index.rst +++ b/boards/arm/nucleo_l476rg/doc/index.rst @@ -145,7 +145,7 @@ Available pins: :align: center :alt: Nucleo L476RG Morpho connectors -For mode details please refer to `STM32 Nucleo-64 board User Manual`_. +For more details please refer to `STM32 Nucleo-64 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_l496zg/doc/index.rst b/boards/arm/nucleo_l496zg/doc/index.rst index 43f6e1fdb4cdd36..49d011b88467510 100644 --- a/boards/arm/nucleo_l496zg/doc/index.rst +++ b/boards/arm/nucleo_l496zg/doc/index.rst @@ -142,7 +142,7 @@ Connections and IOs Nucleo L496ZG Board has 8 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_l4a6zg/doc/index.rst b/boards/arm/nucleo_l4a6zg/doc/index.rst index 79c7caca7bbf670..7e61d9f89076796 100644 --- a/boards/arm/nucleo_l4a6zg/doc/index.rst +++ b/boards/arm/nucleo_l4a6zg/doc/index.rst @@ -147,7 +147,7 @@ Connections and IOs Nucleo L4A6ZG Board has 8 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_l4r5zi/board.cmake b/boards/arm/nucleo_l4r5zi/board.cmake index 037f4a5fd14bc01..0def9a56111a2ed 100644 --- a/boards/arm/nucleo_l4r5zi/board.cmake +++ b/boards/arm/nucleo_l4r5zi/board.cmake @@ -1,6 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") board_runner_args(jlink "--device=STM32L4R5ZI" "--speed=4000") +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/nucleo_l4r5zi/doc/index.rst b/boards/arm/nucleo_l4r5zi/doc/index.rst index 9adb38a2c59a58c..b132403ce2adbd3 100644 --- a/boards/arm/nucleo_l4r5zi/doc/index.rst +++ b/boards/arm/nucleo_l4r5zi/doc/index.rst @@ -160,7 +160,7 @@ Available pins: :align: center :alt: Nucleo L4R5ZI Arduino connectors -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- @@ -219,9 +219,23 @@ Ethernet over USB is configured as the default network interface (EEM) Programming and Debugging ************************* +The NUCLEO-L4R5ZI board includes a ST-LINK/V2 embedded debug tool interface. + +The board is configured to be flashed using west `STM32CubeProgrammer`_ runner, +so its installation is required to be able to flash the board. + +Alternatively, openocd (provided in Zephyr SDK) or JLink can also be used to +flash the board using the ``--runner`` (or ``-r``) option: + +.. code-block:: console + + $ west flash --runner openocd + $ west flash --runner jlink + Connect the Nucleo L4R5ZI to your host computer using the USB port. -Then build and flash an application. Here is an example for the -:ref:`hello_world` application. +Then build and flash an application. + +Here is an example for the :ref:`hello_world` application. Run a serial host program to connect with your Nucleo board: @@ -256,3 +270,6 @@ You should see the following message on the console: .. _STM32 ST-LINK utility: https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stsw-link004.html + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst b/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst index 51675477af41367..0d9b7b37ae032a5 100644 --- a/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst +++ b/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst @@ -234,7 +234,7 @@ Available pins: :align: center :alt: Nucleo L552ZE Q Zio right connector -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_u575zi_q/doc/index.rst b/boards/arm/nucleo_u575zi_q/doc/index.rst index 0de2c364ecf8a52..d9f4c93d753d77e 100644 --- a/boards/arm/nucleo_u575zi_q/doc/index.rst +++ b/boards/arm/nucleo_u575zi_q/doc/index.rst @@ -185,7 +185,7 @@ Connections and IOs Nucleo U575ZI Q Board has 9 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/nucleo_u5a5zj_q/doc/index.rst b/boards/arm/nucleo_u5a5zj_q/doc/index.rst index f877be5c1685227..d9732bf430b21f1 100644 --- a/boards/arm/nucleo_u5a5zj_q/doc/index.rst +++ b/boards/arm/nucleo_u5a5zj_q/doc/index.rst @@ -219,7 +219,7 @@ Connections and IOs Nucleo U5A5ZJ Q Board has 10 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32 Nucleo-144 board User Manual`_. +For more details please refer to `STM32 Nucleo-144 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/pan1783_pan1783a_evb/CMakeLists.txt b/boards/arm/pan1783/CMakeLists.txt similarity index 59% rename from boards/arm/pan1783_pan1783a_evb/CMakeLists.txt rename to boards/arm/pan1783/CMakeLists.txt index 9530e370252986f..a582b3cc819ea14 100644 --- a/boards/arm/pan1783_pan1783a_evb/CMakeLists.txt +++ b/boards/arm/pan1783/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH # SPDX-License-Identifier: Apache-2.0 -if((CONFIG_BOARD_PAN1783_EVB_CPUAPP OR CONFIG_BOARD_PAN1783A_EVB_CPUAPP) AND (CONFIG_BOARD_ENABLE_CPUNET)) +if((CONFIG_BOARD_PAN1783_EVB_CPUAPP OR CONFIG_BOARD_PAN1783A_EVB_CPUAPP OR CONFIG_BOARD_PAN1783A_PA_EVB_CPUAPP) AND (CONFIG_BOARD_ENABLE_CPUNET)) zephyr_library() - zephyr_library_sources(pan1783_pan1783a_evb_cpunet_reset.c) + zephyr_library_sources(pan1783_cpunet_reset.c) endif() diff --git a/boards/arm/pan1783_pan1783a_evb/Kconfig b/boards/arm/pan1783/Kconfig similarity index 83% rename from boards/arm/pan1783_pan1783a_evb/Kconfig rename to boards/arm/pan1783/Kconfig index a699840cad9eaaa..e4f583984590e1a 100644 --- a/boards/arm/pan1783_pan1783a_evb/Kconfig +++ b/boards/arm/pan1783/Kconfig @@ -3,7 +3,7 @@ # Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH # SPDX-License-Identifier: Apache-2.0 -if BOARD_PAN1783_EVB_CPUAPP || BOARD_PAN1783A_EVB_CPUAPP +if BOARD_PAN1783_EVB_CPUAPP || BOARD_PAN1783A_EVB_CPUAPP || BOARD_PAN1783A_PA_EVB_CPUAPP config BOARD_ENABLE_DCDC_APP bool "Application MCU DCDC converter" @@ -35,6 +35,7 @@ config DOMAIN_CPUNET_BOARD string default "pan1783_evb_cpunet" if BOARD_PAN1783_EVB_CPUAPP default "pan1783a_evb_cpunet" if BOARD_PAN1783A_EVB_CPUAPP + default "pan1783a_pa_evb_cpunet" if BOARD_PAN1783A_PA_EVB_CPUAPP depends on BOARD_ENABLE_CPUNET help The board which will be used for CPUNET domain when creating a multi @@ -42,12 +43,13 @@ config DOMAIN_CPUNET_BOARD another board. For example hci_ipc on the nRF5340_cpunet for Bluetooth applications. -endif # BOARD_PAN1783_EVB_CPUAPP || BOARD_PAN1783A_EVB_CPUAPP +endif # BOARD_PAN1783_EVB_CPUAPP || BOARD_PAN1783A_EVB_CPUAPP || BOARD_PAN1783A_PA_EVB_CPUAPP config DOMAIN_CPUAPP_BOARD string default "pan1783_evb_cpuapp" if BOARD_PAN1783_EVB_CPUNET default "pan1783a_evb_cpuapp" if BOARD_PAN1783A_EVB_CPUNET + default "pan1783a_pa_evb_cpuapp" if BOARD_PAN1783A_PA_EVB_CPUNET help The board which will be used for CPUAPP domain when creating a multi image application where one or more images should be located on diff --git a/boards/arm/pan1783_pan1783a_evb/Kconfig.board b/boards/arm/pan1783/Kconfig.board similarity index 70% rename from boards/arm/pan1783_pan1783a_evb/Kconfig.board rename to boards/arm/pan1783/Kconfig.board index cfb5629b24c8894..3fcaaf39e563cb2 100644 --- a/boards/arm/pan1783_pan1783a_evb/Kconfig.board +++ b/boards/arm/pan1783/Kconfig.board @@ -11,6 +11,10 @@ config BOARD_PAN1783A_EVB_CPUAPP bool "PAN1783A EVB (nRF5340) Application MCU" depends on SOC_NRF5340_CPUAPP_QKAA +config BOARD_PAN1783A_PA_EVB_CPUAPP + bool "PAN1783A-PA EVB (nRF5340) Application MCU" + depends on SOC_NRF5340_CPUAPP_QKAA + config BOARD_PAN1783_EVB_CPUNET bool "PAN1783 EVB (NRF5340) Network MCU" depends on SOC_NRF5340_CPUNET_QKAA @@ -18,3 +22,7 @@ config BOARD_PAN1783_EVB_CPUNET config BOARD_PAN1783A_EVB_CPUNET bool "PAN1783A EVB (NRF5340) Network MCU" depends on SOC_NRF5340_CPUNET_QKAA + +config BOARD_PAN1783A_PA_EVB_CPUNET + bool "PAN1783A-PA EVB (NRF5340) Network MCU" + depends on SOC_NRF5340_CPUNET_QKAA diff --git a/boards/arm/pan1783_pan1783a_evb/Kconfig.defconfig b/boards/arm/pan1783/Kconfig.defconfig similarity index 54% rename from boards/arm/pan1783_pan1783a_evb/Kconfig.defconfig rename to boards/arm/pan1783/Kconfig.defconfig index 34daddb0ea74114..47c02a95b7f7be2 100644 --- a/boards/arm/pan1783_pan1783a_evb/Kconfig.defconfig +++ b/boards/arm/pan1783/Kconfig.defconfig @@ -6,13 +6,15 @@ config BOARD default "pan1783_evb_cpuapp" if BOARD_PAN1783_EVB_CPUAPP default "pan1783a_evb_cpuapp" if BOARD_PAN1783A_EVB_CPUAPP + default "pan1783a_pa_evb_cpuapp" if BOARD_PAN1783A_PA_EVB_CPUAPP default "pan1783_evb_cpunet" if BOARD_PAN1783_EVB_CPUNET default "pan1783a_evb_cpunet" if BOARD_PAN1783A_EVB_CPUNET + default "pan1783a_pa_evb_cpunet" if BOARD_PAN1783A_PA_EVB_CPUNET config MBOX_NRFX_IPC default MBOX -if BOARD_PAN1783_EVB_CPUAPP || BOARD_PAN1783A_EVB_CPUAPP +if BOARD_PAN1783_EVB_CPUAPP || BOARD_PAN1783A_EVB_CPUAPP || BOARD_PAN1783A_PA_EVB_CPUAPP choice BT_HCI_BUS_TYPE default BT_HCI_IPC if BT @@ -22,11 +24,11 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD int default 4096 if BT_HCI_IPC -endif # BOARD_PAN1783_EVB_CPUAPP || BOARD_PAN1783A_EVB_CPUAPP +endif # BOARD_PAN1783_EVB_CPUAPP || BOARD_PAN1783A_EVB_CPUAPP || BOARD_PAN1783A_PA_EVB_CPUAPP -if BOARD_PAN1783_EVB_CPUNET || BOARD_PAN1783A_EVB_CPUNET +if BOARD_PAN1783_EVB_CPUNET || BOARD_PAN1783A_EVB_CPUNET || BOARD_PAN1783A_PA_EVB_CPUNET config BT_CTLR default y if BT -endif # BOARD_PAN1783_EVB_CPUNET || BOARD_PAN1783A_EVB_CPUNET +endif # BOARD_PAN1783_EVB_CPUNET || BOARD_PAN1783A_EVB_CPUNET || BOARD_PAN1783A_PA_EVB_CPUNET diff --git a/boards/arm/pan1783_pan1783a_evb/board.cmake b/boards/arm/pan1783/board.cmake similarity index 82% rename from boards/arm/pan1783_pan1783a_evb/board.cmake rename to boards/arm/pan1783/board.cmake index 5fe4b0507c7b461..e8a33e8c7bf1298 100644 --- a/boards/arm/pan1783_pan1783a_evb/board.cmake +++ b/boards/arm/pan1783/board.cmake @@ -1,10 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 -if(CONFIG_BOARD_PAN1783_EVB_CPUAPP OR CONFIG_BOARD_PAN1783A_EVB_CPUAPP) +if(CONFIG_BOARD_PAN1783_EVB_CPUAPP OR CONFIG_BOARD_PAN1783A_EVB_CPUAPP OR CONFIG_BOARD_PAN1783A_PA_EVB_CPUAPP) board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") endif() -if(CONFIG_BOARD_PAN1783_EVB_CPUNET OR CONFIG_BOARD_PAN1783A_EVB_CPUNET) +if(CONFIG_BOARD_PAN1783_EVB_CPUNET OR CONFIG_BOARD_PAN1783A_EVB_CPUNET OR CONFIG_BOARD_PAN1783A_PA_EVB_CPUNET) board_runner_args(jlink "--device=nrf5340_xxaa_net" "--speed=4000") endif() diff --git a/boards/arm/pan1783/doc/img/pan1783_evb.webp b/boards/arm/pan1783/doc/img/pan1783_evb.webp new file mode 100644 index 000000000000000..314252de2399ed2 Binary files /dev/null and b/boards/arm/pan1783/doc/img/pan1783_evb.webp differ diff --git a/boards/arm/pan1783/doc/index.rst b/boards/arm/pan1783/doc/index.rst new file mode 100644 index 000000000000000..95b8b94444b9873 --- /dev/null +++ b/boards/arm/pan1783/doc/index.rst @@ -0,0 +1,73 @@ +.. _pan1783_evb: + +PAN1783, PAN1783A and PAN1783A-PA Evaluation Boards +################################################### + +Overview +******** + +The PAN1783, PAN1783A and PAN1783A-PA Evaluation Boards (pan1783_evb, +pan1783a_evb, pan1783a_pa_evb) are development tools for the PAN1783, +PAN1783A and PAN1783A-PA Modules which are based on the nRF5340 chipset +from Nordic Semiconductor. + +More information about the PAN1783, PAN1783A, PAN1783A-PA Modules and +Evaluation Boards can be found on the `product website`_. + +PAN1783 EVB +*********** + +.. figure:: img/pan1783_evb.webp + :align: center + :alt: PAN1783 EVB + + PAN1783 EVB (Credit: Panasonic) + +PAN1783A EVB +************ + +The PAN1783A EVB essentially looks like a PAN1783 EVB, except that it is +equipped with a UFL connector on X4. + +PAN1783A-PA EVB +*************** + +The PAN1783A-PA EVB essentially resembles a PAN1783 EVB, with the addition +of a UFL connector on X4 and a power amplifier. + +Usage +***** + +For detailed information, you can find the +`pan1783_evb user guide`_ / `pan1783a_evb user guide`_ / `pan1783a_pa_evb user guide`_ +for the Evaluation Boards in the `Panasonic Wireless Connectivity Development Hub`_. + +The User Guide contains (amongst other things) detailed information about + +* pin mapping +* powering options +* breakout pin header interface +* current consumption measurement +* software development + +The schematics for the PAN1783/PAN1783A/PAN1783A-PA Evaluation Boards are +available in the `download section PAN1783`_ / `download section PAN1783A`_ / `download section PAN1783A-PA`_ +of the `Panasonic Wireless Connectivity Development Hub`_. + +Programming and Debugging +************************* + +Please use the ``pan1783_evb_cpuapp``, ``pan1783a_evb_cpuapp`` or +``pan1783a_pa_evb_cpuapp`` for application core and ``pan1783_evb_cpunet``, +``pan1783a_evb_cpunet`` or ``pan1783a_pa_evb_cpunet`` board configuration +for network core when :ref:`build_an_application` and :ref:`application_run`. + +.. target-notes:: +.. _product website: https://industry.panasonic.eu/products/devices/wireless-connectivity/bluetooth-low-energy-modules +.. _Panasonic Wireless Connectivity Development Hub: https://pideu.panasonic.de/development-hub/ +.. _pan1783_evb user guide: https://pideu.panasonic.de/development-hub/pan1783/evaluation_board/user_guide/ +.. _pan1783a_evb user guide: https://pideu.panasonic.de/development-hub/pan1783a/evaluation_board/user_guide/ +.. _pan1783a_pa_evb user guide: https://pideu.panasonic.de/development-hub/pan1783a_pa/evaluation_board/user_guide/ +.. _download section PAN1783: https://pideu.panasonic.de/development-hub/pan1783/downloads/ +.. _download section PAN1783A: https://pideu.panasonic.de/development-hub/pan1783a/downloads/ +.. _download section PAN1783A-PA: https://pideu.panasonic.de/development-hub/pan1783a_pa/downloads/ diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpuapp_common-pinctrl.dtsi b/boards/arm/pan1783/pan1783_cpuapp_common-pinctrl.dtsi similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpuapp_common-pinctrl.dtsi rename to boards/arm/pan1783/pan1783_cpuapp_common-pinctrl.dtsi diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpuapp_common.dtsi b/boards/arm/pan1783/pan1783_cpuapp_common.dtsi similarity index 98% rename from boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpuapp_common.dtsi rename to boards/arm/pan1783/pan1783_cpuapp_common.dtsi index 82f49665338f07c..77d093a5d4003ee 100644 --- a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpuapp_common.dtsi +++ b/boards/arm/pan1783/pan1783_cpuapp_common.dtsi @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include "pan1783_pan1783a_cpuapp_common-pinctrl.dtsi" +#include "pan1783_cpuapp_common-pinctrl.dtsi" #include / { @@ -297,4 +297,4 @@ zephyr_udc0: &usbd { }; /* Include partition configuration file */ -#include "pan1783_pan1783a_cpuapp_partition_conf.dtsi" +#include "pan1783_cpuapp_partition_conf.dtsi" diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpuapp_partition_conf.dtsi b/boards/arm/pan1783/pan1783_cpuapp_partition_conf.dtsi similarity index 93% rename from boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpuapp_partition_conf.dtsi rename to boards/arm/pan1783/pan1783_cpuapp_partition_conf.dtsi index 0ddf9287c7ee3e8..6eb6792c9969598 100644 --- a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpuapp_partition_conf.dtsi +++ b/boards/arm/pan1783/pan1783_cpuapp_partition_conf.dtsi @@ -35,4 +35,4 @@ }; /* Include shared RAM configuration file */ -#include "pan1783_pan1783a_shared_sram_planning_conf.dtsi" +#include "pan1783_shared_sram_planning_conf.dtsi" diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpunet-pinctrl.dtsi b/boards/arm/pan1783/pan1783_cpunet-pinctrl.dtsi similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpunet-pinctrl.dtsi rename to boards/arm/pan1783/pan1783_cpunet-pinctrl.dtsi diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpunet_common.dtsi b/boards/arm/pan1783/pan1783_cpunet_common.dtsi similarity index 97% rename from boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpunet_common.dtsi rename to boards/arm/pan1783/pan1783_cpunet_common.dtsi index 8cd2d154e8e5e18..5b5e7735e4a4c38 100644 --- a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_cpunet_common.dtsi +++ b/boards/arm/pan1783/pan1783_cpunet_common.dtsi @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include "pan1783_pan1783a_cpunet-pinctrl.dtsi" +#include "pan1783_cpunet-pinctrl.dtsi" #include / { @@ -204,4 +204,4 @@ arduino_spi: &spi0 { }; /* Include shared RAM configuration file */ -#include "pan1783_pan1783a_shared_sram_planning_conf.dtsi" +#include "pan1783_shared_sram_planning_conf.dtsi" diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_evb_cpunet_reset.c b/boards/arm/pan1783/pan1783_cpunet_reset.c similarity index 90% rename from boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_evb_cpunet_reset.c rename to boards/arm/pan1783/pan1783_cpunet_reset.c index 0c957e0ed3ba5b3..529051ec62943fb 100644 --- a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_evb_cpunet_reset.c +++ b/boards/arm/pan1783/pan1783_cpunet_reset.c @@ -15,6 +15,8 @@ LOG_MODULE_REGISTER(pan1783_evb_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); #elif defined(CONFIG_BOARD_PAN1783A_EVB_CPUAPP) LOG_MODULE_REGISTER(pan1783a_evb_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); +#elif defined(CONFIG_BOARD_PAN1783A_PA_EVB_CPUAPP) +LOG_MODULE_REGISTER(pan1783a_pa_evb_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); #else #error "No board selected!" #endif diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpuapp.dts b/boards/arm/pan1783/pan1783_evb_cpuapp.dts similarity index 90% rename from boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpuapp.dts rename to boards/arm/pan1783/pan1783_evb_cpuapp.dts index b65858f89fa6fb5..54f71dd87d5b20d 100644 --- a/boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpuapp.dts +++ b/boards/arm/pan1783/pan1783_evb_cpuapp.dts @@ -6,7 +6,7 @@ /dts-v1/; #include -#include "pan1783_pan1783a_cpuapp_common.dtsi" +#include "pan1783_cpuapp_common.dtsi" / { model = "Panasonic PAN1783 EVB (NRF5340) Application"; diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpuapp.yaml b/boards/arm/pan1783/pan1783_evb_cpuapp.yaml similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpuapp.yaml rename to boards/arm/pan1783/pan1783_evb_cpuapp.yaml diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpuapp_defconfig b/boards/arm/pan1783/pan1783_evb_cpuapp_defconfig similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpuapp_defconfig rename to boards/arm/pan1783/pan1783_evb_cpuapp_defconfig diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpunet.dts b/boards/arm/pan1783/pan1783_evb_cpunet.dts similarity index 80% rename from boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpunet.dts rename to boards/arm/pan1783/pan1783_evb_cpunet.dts index bd84c622126508e..7063e53af46d504 100644 --- a/boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpunet.dts +++ b/boards/arm/pan1783/pan1783_evb_cpunet.dts @@ -6,7 +6,7 @@ /dts-v1/; #include -#include "pan1783_pan1783a_cpunet_common.dtsi" +#include "pan1783_cpunet_common.dtsi" / { model = "Panasonic PAN1783 EVB (NRF5340) Network"; @@ -20,4 +20,4 @@ }; /* Include shared RAM configuration file */ -#include "pan1783_pan1783a_shared_sram_planning_conf.dtsi" +#include "pan1783_shared_sram_planning_conf.dtsi" diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpunet.yaml b/boards/arm/pan1783/pan1783_evb_cpunet.yaml similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpunet.yaml rename to boards/arm/pan1783/pan1783_evb_cpunet.yaml diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpunet_defconfig b/boards/arm/pan1783/pan1783_evb_cpunet_defconfig similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783_evb_cpunet_defconfig rename to boards/arm/pan1783/pan1783_evb_cpunet_defconfig diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_shared_sram_planning_conf.dtsi b/boards/arm/pan1783/pan1783_shared_sram_planning_conf.dtsi similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783_pan1783a_shared_sram_planning_conf.dtsi rename to boards/arm/pan1783/pan1783_shared_sram_planning_conf.dtsi diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpuapp.dts b/boards/arm/pan1783/pan1783a_evb_cpuapp.dts similarity index 90% rename from boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpuapp.dts rename to boards/arm/pan1783/pan1783a_evb_cpuapp.dts index dc3ff1357e48674..29f0dcb796c4d93 100644 --- a/boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpuapp.dts +++ b/boards/arm/pan1783/pan1783a_evb_cpuapp.dts @@ -6,7 +6,7 @@ /dts-v1/; #include -#include "pan1783_pan1783a_cpuapp_common.dtsi" +#include "pan1783_cpuapp_common.dtsi" / { model = "Panasonic PAN1783A EVB (NRF5340) Application"; diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpuapp.yaml b/boards/arm/pan1783/pan1783a_evb_cpuapp.yaml similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpuapp.yaml rename to boards/arm/pan1783/pan1783a_evb_cpuapp.yaml diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpuapp_defconfig b/boards/arm/pan1783/pan1783a_evb_cpuapp_defconfig similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpuapp_defconfig rename to boards/arm/pan1783/pan1783a_evb_cpuapp_defconfig diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpunet.dts b/boards/arm/pan1783/pan1783a_evb_cpunet.dts similarity index 80% rename from boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpunet.dts rename to boards/arm/pan1783/pan1783a_evb_cpunet.dts index 8be0b5966a89db3..9cd0409a4326946 100644 --- a/boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpunet.dts +++ b/boards/arm/pan1783/pan1783a_evb_cpunet.dts @@ -6,7 +6,7 @@ /dts-v1/; #include -#include "pan1783_pan1783a_cpunet_common.dtsi" +#include "pan1783_cpunet_common.dtsi" / { model = "Panasonic PAN1783A EVB (NRF5340) Network"; @@ -20,4 +20,4 @@ }; /* Include shared RAM configuration file */ -#include "pan1783_pan1783a_shared_sram_planning_conf.dtsi" +#include "pan1783_shared_sram_planning_conf.dtsi" diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpunet.yaml b/boards/arm/pan1783/pan1783a_evb_cpunet.yaml similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpunet.yaml rename to boards/arm/pan1783/pan1783a_evb_cpunet.yaml diff --git a/boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpunet_defconfig b/boards/arm/pan1783/pan1783a_evb_cpunet_defconfig similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pan1783a_evb_cpunet_defconfig rename to boards/arm/pan1783/pan1783a_evb_cpunet_defconfig diff --git a/boards/arm/pan1783/pan1783a_pa_evb_cpuapp.dts b/boards/arm/pan1783/pan1783a_pa_evb_cpuapp.dts new file mode 100644 index 000000000000000..aba6e9281e2111d --- /dev/null +++ b/boards/arm/pan1783/pan1783a_pa_evb_cpuapp.dts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "pan1783_cpuapp_common.dtsi" + +/ { + model = "Panasonic PAN1783A-PA EVB (NRF5340) Application"; + compatible = "panasonic,pan1783a_pa-evb-cpuapp"; + + chosen { + zephyr,sram = &sram0_image; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,sram-secure-partition = &sram0_s; + }; +}; + +&gpio_fwd { + /delete-node/ uart; + + status = "okay"; + fem { + gpios = <&gpio0 19 0>, <&gpio0 21 0>; + }; +}; diff --git a/boards/arm/pan1783/pan1783a_pa_evb_cpuapp.yaml b/boards/arm/pan1783/pan1783a_pa_evb_cpuapp.yaml new file mode 100644 index 000000000000000..0bc70dab27375a2 --- /dev/null +++ b/boards/arm/pan1783/pan1783a_pa_evb_cpuapp.yaml @@ -0,0 +1,21 @@ +identifier: pan1783a_pa_evb_cpuapp +name: PAN1783A-PA-EVB-application-MCU +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 448 +flash: 1024 +supported: + - gpio + - i2c + - i2s + - pwm + - watchdog + - usb_cdc + - usb_device + - netif:openthread + - gpio +vendor: panasonic diff --git a/boards/arm/pan1783/pan1783a_pa_evb_cpuapp_defconfig b/boards/arm/pan1783/pan1783a_pa_evb_cpuapp_defconfig new file mode 100644 index 000000000000000..f58bdce8bfc0c03 --- /dev/null +++ b/boards/arm/pan1783/pan1783a_pa_evb_cpuapp_defconfig @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUAPP_QKAA=y +CONFIG_BOARD_PAN1783A_PA_EVB_CPUAPP=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# clock config +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y +CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n diff --git a/boards/arm/pan1783/pan1783a_pa_evb_cpunet.dts b/boards/arm/pan1783/pan1783a_pa_evb_cpunet.dts new file mode 100644 index 000000000000000..1b345aaa94526be --- /dev/null +++ b/boards/arm/pan1783/pan1783a_pa_evb_cpunet.dts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Panasonic Industrial Devices Europe GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "pan1783_cpunet_common.dtsi" + +/ { + model = "Panasonic PAN1783A-PA EVB (NRF5340) Network"; + compatible = "panasonic,pan1783a_pa-evb-cpunet"; + + chosen { + zephyr,sram = &sram1; + zephyr,flash = &flash1; + zephyr,code-partition = &slot0_partition; + }; + + nrf_radio_fem: fem_node { + compatible = "skyworks,sky66407-11", "generic-fem-two-ctrl-pins"; + ctx-gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>; + crx-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>; + }; +}; + +&radio { + fem = <&nrf_radio_fem>; +}; + +/* Include shared RAM configuration file */ +#include "pan1783_shared_sram_planning_conf.dtsi" diff --git a/boards/arm/pan1783/pan1783a_pa_evb_cpunet.yaml b/boards/arm/pan1783/pan1783a_pa_evb_cpunet.yaml new file mode 100644 index 000000000000000..98a2f2908de226a --- /dev/null +++ b/boards/arm/pan1783/pan1783a_pa_evb_cpunet.yaml @@ -0,0 +1,14 @@ +identifier: pan1783a_pa_evb_cpunet +name: PAN1783A-PA-EVB-network-MCU +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 64 +flash: 256 +supported: + - watchdog + - gpio +vendor: panasonic diff --git a/boards/arm/pan1783/pan1783a_pa_evb_cpunet_defconfig b/boards/arm/pan1783/pan1783a_pa_evb_cpunet_defconfig new file mode 100644 index 000000000000000..3ba18cd433a00c3 --- /dev/null +++ b/boards/arm/pan1783/pan1783a_pa_evb_cpunet_defconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF53X=y +CONFIG_SOC_NRF5340_CPUNET_QKAA=y +CONFIG_BOARD_PAN1783A_PA_EVB_CPUNET=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y + +# clock config +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y +CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n diff --git a/boards/arm/pan1783_pan1783a_evb/pre_dt_board.cmake b/boards/arm/pan1783/pre_dt_board.cmake similarity index 100% rename from boards/arm/pan1783_pan1783a_evb/pre_dt_board.cmake rename to boards/arm/pan1783/pre_dt_board.cmake diff --git a/boards/arm/pan1783_pan1783a_evb/doc/img/pan1783_evb.jpg b/boards/arm/pan1783_pan1783a_evb/doc/img/pan1783_evb.jpg deleted file mode 100644 index 273253cfcf95df4..000000000000000 Binary files a/boards/arm/pan1783_pan1783a_evb/doc/img/pan1783_evb.jpg and /dev/null differ diff --git a/boards/arm/pan1783_pan1783a_evb/doc/img/pan1783a_evb.jpg b/boards/arm/pan1783_pan1783a_evb/doc/img/pan1783a_evb.jpg deleted file mode 100644 index aeab9bdb96a1143..000000000000000 Binary files a/boards/arm/pan1783_pan1783a_evb/doc/img/pan1783a_evb.jpg and /dev/null differ diff --git a/boards/arm/pan1783_pan1783a_evb/doc/index.rst b/boards/arm/pan1783_pan1783a_evb/doc/index.rst deleted file mode 100644 index 3c9aff5654ab02f..000000000000000 --- a/boards/arm/pan1783_pan1783a_evb/doc/index.rst +++ /dev/null @@ -1,62 +0,0 @@ -.. _pan1783_evb: - -PAN1783/PAN1783A Evaluation Board -################################# - -Overview -******** - -The PAN1783/PAN1783A Evaluation Board (pan1783_evb/pan1783a_evb) is a -development tool for the PAN1783/PAN1783A Module which is based on the -nRF5340 chipset from Nordic Semiconductor. - -You can find more information about the PAN1783/PAN1783A Module and -Evaluation Board on the `product website pan1783`_ / `product website pan1783a`_. - -.. figure:: img/pan1783_evb.jpg - :align: center - :alt: PAN1783 EVB - - PAN1783 EVB (Credit: Panasonic) - -.. figure:: img/pan1783a_evb.jpg - :align: center - :alt: PAN1783A EVB - - PAN1783A EVB (Credit: Panasonic) - -Usage -***** - -For detailed information, you can find the -`pan1783_evb user guide`_ / `pan1783a_evb user guide`_ for the -Evaluation Boards in the -`Panasonic Wireless Connectivity Development Hub`_. - -The User Guide contains (amongst other things) detailed information about - -* pin mapping -* powering options -* breakout pin header interface -* current consumption measurement -* software development - -The schematics for the PAN1783/PAN1783A Evaluation Boards are available in the -`download section pan1783`_ / `download section pan1783a`_ of the -`Panasonic Wireless Connectivity Development Hub`_. - -Programming and Debugging -************************* - -Please use the ``pan1783_evb_cpuapp`` or ``pan1783a_evb_cpuapp`` for application -core and ``pan1783_evb_cpunet`` or ``pan1783_evb_cpunet`` board configuration -for network core when :ref:`build_an_application` and :ref:`application_run`. - -.. target-notes:: -.. _product website pan1783: https://industry.panasonic.eu/products/devices/wireless-connectivity/bluetooth-low-energy-modules/pan1783-nrf5340 -.. _product website pan1783a: https://industry.panasonic.eu/products/devices/wireless-connectivity/bluetooth-low-energy-modules/pan1783a-nrf5340 -.. _Panasonic Wireless Connectivity Development Hub: https://pideu.panasonic.de/development-hub/ -.. _pan1783_evb user guide: https://pideu.panasonic.de/development-hub/pan1783/evaluation_board/user_guide/ -.. _pan1783a_evb user guide: https://pideu.panasonic.de/development-hub/pan1783a/evaluation_board/user_guide/ -.. _download section pan1783: https://pideu.panasonic.de/development-hub/pan1783/downloads/ -.. _download section pan1783a: https://pideu.panasonic.de/development-hub/pan1783a/downloads/ diff --git a/boards/arm/pandora_stm32l475/doc/index.rst b/boards/arm/pandora_stm32l475/doc/index.rst index 62a903faf78441c..76da038e9ec4b0b 100644 --- a/boards/arm/pandora_stm32l475/doc/index.rst +++ b/boards/arm/pandora_stm32l475/doc/index.rst @@ -136,7 +136,7 @@ Connections and IOs STM32L475 Pandora Board has 8 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32L475 Pandora board User Manual`_. +For more details please refer to `STM32L475 Pandora board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/rzt2m_starterkit/doc/index.rst b/boards/arm/rzt2m_starterkit/doc/index.rst index 1fa6a13b6f93c6d..72dc6615f64b6f4 100644 --- a/boards/arm/rzt2m_starterkit/doc/index.rst +++ b/boards/arm/rzt2m_starterkit/doc/index.rst @@ -22,6 +22,7 @@ Hardware The board utilizes the SoC of part no. R9A07G075M24GBG, with 2MB of RAM. It has several on-board memory components: + * SDRAM (256MBit), * NOR Flash (256MBit), * Octa Flash (512MBit), @@ -30,6 +31,7 @@ It has several on-board memory components: * I2C EEPROM (32Kbit). The communication interfaces include: + * Debug interfaces (J-Link, MIPI-10, MIPI-20), * Ethernet, * CAN, @@ -62,6 +64,7 @@ Connections and IOs =================== By default, the board is configured for use with: + * UART0 connected to the USB serial port (pins K18, K19), * UART3 connected to the PMOD Header (J25, pins H16, G20), * LEDs defined as `led0`, `led1`, `led2` and `led3`, diff --git a/boards/arm/scobc_module1/scobc_module1_defconfig b/boards/arm/scobc_module1/scobc_module1_defconfig index 8ec2b6795577bd6..ecadcfc07bd92ff 100644 --- a/boards/arm/scobc_module1/scobc_module1_defconfig +++ b/boards/arm/scobc_module1/scobc_module1_defconfig @@ -14,4 +14,3 @@ CONFIG_UART_CONSOLE=y CONFIG_XIP=n CONFIG_FLASH_SIZE=0 CONFIG_FLASH_BASE_ADDRESS=0x0 -CONFIG_BOOTLOADER_SRAM_SIZE=0 diff --git a/boards/arm/sensortile_box/sensortile_box.dts b/boards/arm/sensortile_box/sensortile_box.dts index b86220208405977..4c5a9654b3d6dcd 100644 --- a/boards/arm/sensortile_box/sensortile_box.dts +++ b/boards/arm/sensortile_box/sensortile_box.dts @@ -165,16 +165,15 @@ pinctrl-0 = <&spi2_sck_pd1 &spi2_miso_pd3 &spi2_mosi_pc3>; pinctrl-names = "default"; status = "okay"; - cs-gpios = <&gpiod 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + cs-gpios = <&gpiod 0 GPIO_ACTIVE_LOW>; spbtle_1s_sensortile_box: spbtle-1s@0 { - compatible = "zephyr,bt-hci-spi", "st,hci-spi-v2"; + compatible = "st,hci-spi-v2"; reg = <0>; - reset-gpios = <&gpioa 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + reset-gpios = <&gpioa 8 GPIO_ACTIVE_LOW>; irq-gpios = <&gpiod 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; - spi-max-frequency = <1000000>; + spi-max-frequency = ; spi-cpha; spi-hold-cs; - controller-data-delay-us = <0>; reset-assert-duration-ms = <6>; }; }; diff --git a/boards/arm/sensortile_box_pro/Kconfig.defconfig b/boards/arm/sensortile_box_pro/Kconfig.defconfig index e37f5e4f5bfb609..48b55275be3dd7d 100644 --- a/boards/arm/sensortile_box_pro/Kconfig.defconfig +++ b/boards/arm/sensortile_box_pro/Kconfig.defconfig @@ -8,6 +8,24 @@ if BOARD_SENSORTILE_BOX_PRO config BOARD default "sensortile_box_pro" +if BT + +config SPI + default y + +choice BT_HCI_BUS_TYPE + default BT_SPI +endchoice + +config BT_BLUENRG_ACI + default y + +# Disable Flow control +config BT_HCI_ACL_FLOW_CONTROL + default n + +endif # BT + config SPI_STM32_INTERRUPT default y depends on SPI diff --git a/boards/arm/sensortile_box_pro/sensortile_box_pro.dts b/boards/arm/sensortile_box_pro/sensortile_box_pro.dts index a90903667090cd7..8c159eb831fe20f 100644 --- a/boards/arm/sensortile_box_pro/sensortile_box_pro.dts +++ b/boards/arm/sensortile_box_pro/sensortile_box_pro.dts @@ -158,10 +158,28 @@ stm32_lp_tick_source: &lptim1 { }; &spi1 { - pinctrl-0 = <&spi1_nss_pe12 &spi1_sck_pe13 - &spi1_miso_pe14 &spi1_mosi_pe15>; + pinctrl-0 = <&spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pa7>; pinctrl-names = "default"; + cs-gpios = <&gpioa 2 GPIO_ACTIVE_LOW>; status = "okay"; + + bluenrg-lp@0 { + compatible = "st,hci-spi-v2"; + reg = <0>; + irq-gpios = <&gpiod 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; + reset-gpios = <&gpiod 4 GPIO_ACTIVE_LOW>; + spi-cpol; + spi-cpha; + spi-hold-cs; + spi-max-frequency = ; + controller-data-delay-us = <0>; + reset-assert-duration-ms = <6>; + }; +}; + +&spi1_sck_pa5 { + /delete-property/ bias-pull-down; + bias-pull-up; /* Idle state for the clock pin is high-level due to SPI mode 3 */ }; &spi2 { diff --git a/boards/arm/sensortile_box_pro/sensortile_box_pro.yaml b/boards/arm/sensortile_box_pro/sensortile_box_pro.yaml index da81ee182e1de94..14624c77f7d3b94 100644 --- a/boards/arm/sensortile_box_pro/sensortile_box_pro.yaml +++ b/boards/arm/sensortile_box_pro/sensortile_box_pro.yaml @@ -9,6 +9,7 @@ toolchain: supported: - pwm - spi + - ble - i2c - gpio - usb device diff --git a/boards/arm/stm32f072_eval/doc/index.rst b/boards/arm/stm32f072_eval/doc/index.rst index 4872f85785b8e08..49b6577935c7c4c 100644 --- a/boards/arm/stm32f072_eval/doc/index.rst +++ b/boards/arm/stm32f072_eval/doc/index.rst @@ -110,7 +110,7 @@ Pin Mapping STM32F072-EVAL Discovery kit has 6 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to STM32F072-EVAL board User Manual. +For more details please refer to STM32F072-EVAL board User Manual. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f072b_disco/doc/index.rst b/boards/arm/stm32f072b_disco/doc/index.rst index 3756926ec4cbb75..a2c51e51cddd74c 100644 --- a/boards/arm/stm32f072b_disco/doc/index.rst +++ b/boards/arm/stm32f072b_disco/doc/index.rst @@ -108,7 +108,7 @@ Pin Mapping STM32F072B-DISCO Discovery kit has 6 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32F072B-DISCO board User Manual`_. +For more details please refer to `STM32F072B-DISCO board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f0_disco/doc/index.rst b/boards/arm/stm32f0_disco/doc/index.rst index e2910793d720e81..daf0e1f06d39a6d 100644 --- a/boards/arm/stm32f0_disco/doc/index.rst +++ b/boards/arm/stm32f0_disco/doc/index.rst @@ -89,7 +89,7 @@ Default Zephyr Peripheral Mapping: - UART_2_TX : PA2 - UART_2_RX : PA3 -For mode details please refer to `STM32F0DISCOVERY board User Manual`_. +For more details please refer to `STM32F0DISCOVERY board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/stm32f3_disco/doc/index.rst b/boards/arm/stm32f3_disco/doc/index.rst index a94083fa2c738a1..5a0dc214e06ed4a 100644 --- a/boards/arm/stm32f3_disco/doc/index.rst +++ b/boards/arm/stm32f3_disco/doc/index.rst @@ -123,7 +123,7 @@ Pin Mapping STM32F3DISCOVERY Discovery kit has 6 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32F3DISCOVERY board User Manual`_. +For more details please refer to `STM32F3DISCOVERY board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f3_seco_d23/doc/index.rst b/boards/arm/stm32f3_seco_d23/doc/index.rst index dd66622bf314d1b..0fbf54dd9aee1c1 100644 --- a/boards/arm/stm32f3_seco_d23/doc/index.rst +++ b/boards/arm/stm32f3_seco_d23/doc/index.rst @@ -96,8 +96,10 @@ Pin Mapping SBC-3.5-PX30 has 6 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. + For mode details please refer to `SECO SBC-3.5-PX30 board User Manual`_. + Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f411e_disco/doc/index.rst b/boards/arm/stm32f411e_disco/doc/index.rst index d15dc7728c7d32c..12a057ff1ade341 100644 --- a/boards/arm/stm32f411e_disco/doc/index.rst +++ b/boards/arm/stm32f411e_disco/doc/index.rst @@ -96,7 +96,7 @@ Pin Mapping STM32F411E-DISCO Discovery kit has 5 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `32F411EDISCOVERY board User Manual`_. +For more details please refer to `32F411EDISCOVERY board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f412g_disco/doc/index.rst b/boards/arm/stm32f412g_disco/doc/index.rst index b79f9b18a0a0eab..8bd0bd588f10c4a 100644 --- a/boards/arm/stm32f412g_disco/doc/index.rst +++ b/boards/arm/stm32f412g_disco/doc/index.rst @@ -113,7 +113,7 @@ Pin Mapping STM32F412G-DISCO Discovery kit has 8 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `32F412GDISCOVERY board User Manual`_. +For more details please refer to `32F412GDISCOVERY board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f429i_disc1/doc/index.rst b/boards/arm/stm32f429i_disc1/doc/index.rst index ba2317772a380ef..9b90abf0dbbb21b 100644 --- a/boards/arm/stm32f429i_disc1/doc/index.rst +++ b/boards/arm/stm32f429i_disc1/doc/index.rst @@ -113,7 +113,7 @@ Pin Mapping The STM32F429I-DISC1 Discovery kit has 8 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32F429I-DISC1 board User Manual`_. +For more details please refer to `STM32F429I-DISC1 board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f469i_disco/doc/index.rst b/boards/arm/stm32f469i_disco/doc/index.rst index 7ba1d7c71e32c45..658f2a7b75e755c 100644 --- a/boards/arm/stm32f469i_disco/doc/index.rst +++ b/boards/arm/stm32f469i_disco/doc/index.rst @@ -113,7 +113,7 @@ Pin Mapping STM32F469I-DISCO Discovery kit has 9 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `32F469IDISCOVERY board User Manual`_. +For more details please refer to `32F469IDISCOVERY board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f4_disco/doc/index.rst b/boards/arm/stm32f4_disco/doc/index.rst index 8ea4ef9893c19dc..15dadab7fbf0948 100644 --- a/boards/arm/stm32f4_disco/doc/index.rst +++ b/boards/arm/stm32f4_disco/doc/index.rst @@ -114,7 +114,7 @@ Pin Mapping STM32F4DISCOVERY Discovery kit has 8 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32F4DISCOVERY board User Manual`_. +For more details please refer to `STM32F4DISCOVERY board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f723e_disco/doc/index.rst b/boards/arm/stm32f723e_disco/doc/index.rst index 5ebcc65c392ec41..c6e34cbbe91e3d8 100644 --- a/boards/arm/stm32f723e_disco/doc/index.rst +++ b/boards/arm/stm32f723e_disco/doc/index.rst @@ -99,7 +99,7 @@ Pin Mapping STM32F723E Discovery kit has 7 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `32F723E-DISCO board User Manual`_. +For more details please refer to `32F723E-DISCO board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f746g_disco/doc/index.rst b/boards/arm/stm32f746g_disco/doc/index.rst index c9b77967be9de1b..714a627ec4a07c2 100644 --- a/boards/arm/stm32f746g_disco/doc/index.rst +++ b/boards/arm/stm32f746g_disco/doc/index.rst @@ -130,7 +130,7 @@ Pin Mapping STM32F746G Discovery kit has 9 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `32F746G-DISCO board User Manual`_. +For more details please refer to `32F746G-DISCO board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f7508_dk/doc/index.rst b/boards/arm/stm32f7508_dk/doc/index.rst index a3f39f37e5e871f..699285fcd907483 100644 --- a/boards/arm/stm32f7508_dk/doc/index.rst +++ b/boards/arm/stm32f7508_dk/doc/index.rst @@ -125,7 +125,7 @@ Pin Mapping STM32F7508-DK Discovery kit has 9 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `32F7508-DK board User Manual`_. +For more details please refer to `32F7508-DK board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32f769i_disco/doc/index.rst b/boards/arm/stm32f769i_disco/doc/index.rst index d2183087b955245..203beb6f48a9236 100644 --- a/boards/arm/stm32f769i_disco/doc/index.rst +++ b/boards/arm/stm32f769i_disco/doc/index.rst @@ -132,7 +132,7 @@ Pin Mapping STM32F769I Discovery kit has 9 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `32F769I-DISCO board User Manual`_. +For more details please refer to `32F769I-DISCO board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32g071b_disco/doc/index.rst b/boards/arm/stm32g071b_disco/doc/index.rst index d7071c3d3d2b3f2..2c9cbea31767ee1 100644 --- a/boards/arm/stm32g071b_disco/doc/index.rst +++ b/boards/arm/stm32g071b_disco/doc/index.rst @@ -109,7 +109,7 @@ Default Zephyr Peripheral Mapping: - RDCC1 : PB12 (Enable Door Sense on CC1) -For mode details please refer to `STM32G0 Discovery board User Manual`_. +For more details please refer to `STM32G0 Discovery board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/stm32g081b_eval/doc/index.rst b/boards/arm/stm32g081b_eval/doc/index.rst index 3e2268446c3cb57..970ec32dd0ab5b2 100644 --- a/boards/arm/stm32g081b_eval/doc/index.rst +++ b/boards/arm/stm32g081b_eval/doc/index.rst @@ -147,7 +147,7 @@ Default Zephyr Peripheral Mapping: - LED3 : PD8 - LED4 : PD9 -For mode details please refer to `STM32G0 Evaluation board User Manual`_. +For more details please refer to `STM32G0 Evaluation board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/stm32h573i_dk/doc/index.rst b/boards/arm/stm32h573i_dk/doc/index.rst index f7806f52dde2738..a41a12f0c821a8d 100644 --- a/boards/arm/stm32h573i_dk/doc/index.rst +++ b/boards/arm/stm32h573i_dk/doc/index.rst @@ -17,7 +17,7 @@ the STM32H573I-DK Discovery board: - USB Type-C |trade| Host and device with USB power-delivery controller - SAI Audio DAC stereo with one audio jacks for input/output, - ST MEMS digital microphone with PDM interface -- Octo-SPI interface connected to 152Mbit Octo-SPI NORFlash memory device (MX25LM51245GXDI00 from MACRONIX) +- Octo-SPI interface connected to 512Mbit Octo-SPI NORFlash memory device (MX25LM51245GXDI00 from MACRONIX) - 10/100-Mbit Ethernet, - microSD |trade| - A Wi‑Fi® add-on board @@ -223,7 +223,7 @@ Connections and IOs STM32H573I-DK Discovery Board has 9 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32H573I-DK Discovery board User Manual`_. +For more details please refer to `STM32H573I-DK Discovery board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32h735g_disco/doc/index.rst b/boards/arm/stm32h735g_disco/doc/index.rst index 210756e15675642..473dcfa08c21572 100644 --- a/boards/arm/stm32h735g_disco/doc/index.rst +++ b/boards/arm/stm32h735g_disco/doc/index.rst @@ -75,7 +75,7 @@ The default configuration per core can be found in the defconfig file: Pin Mapping =========== -For mode details please refer to `STM32H735G-DISCO website`_. +For more details please refer to `STM32H735G-DISCO website`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32h747i_disco/doc/index.rst b/boards/arm/stm32h747i_disco/doc/index.rst index d020a3ed94e48d8..6fc553ab42e52b5 100644 --- a/boards/arm/stm32h747i_disco/doc/index.rst +++ b/boards/arm/stm32h747i_disco/doc/index.rst @@ -99,7 +99,7 @@ Pin Mapping STM32H747I Discovery kit has 9 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32H747I-DISCO website`_. +For more details please refer to `STM32H747I-DISCO website`_. Default Zephyr Peripheral Mapping: ---------------------------------- @@ -172,6 +172,10 @@ command, for example: :shield: st_b_lcd40_dsi1_mb1166 :goals: build flash +.. note:: + Currently only the older version MB1166-A03 is supported by Zephyr. + The newer version MB1166-A09 does not get initialized correctly (see :github:`60888`). + Resources sharing ================= diff --git a/boards/arm/stm32h750b_dk/doc/index.rst b/boards/arm/stm32h750b_dk/doc/index.rst index 5b61e499e8f25df..6ac1aa15d34d8a4 100644 --- a/boards/arm/stm32h750b_dk/doc/index.rst +++ b/boards/arm/stm32h750b_dk/doc/index.rst @@ -65,7 +65,7 @@ The default configuration per core can be found in the defconfig file: Pin Mapping =========== -For mode details please refer to `STM32H750B-DK website`_. +For more details please refer to `STM32H750B-DK website`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32h7b3i_dk/doc/index.rst b/boards/arm/stm32h7b3i_dk/doc/index.rst index 549594bb3cc8b3c..83d188584265096 100644 --- a/boards/arm/stm32h7b3i_dk/doc/index.rst +++ b/boards/arm/stm32h7b3i_dk/doc/index.rst @@ -74,7 +74,7 @@ The default configuration per core can be found in the defconfig file: Pin Mapping =========== -For mode details please refer to `STM32H7B3I-DK website`_. +For more details please refer to `STM32H7B3I-DK website`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32l1_disco/doc/index.rst b/boards/arm/stm32l1_disco/doc/index.rst index 65bb4bc028f47dd..a968cebc7928f4e 100644 --- a/boards/arm/stm32l1_disco/doc/index.rst +++ b/boards/arm/stm32l1_disco/doc/index.rst @@ -125,7 +125,7 @@ Default Zephyr Peripheral Mapping: - SPI2_MISO : PB14 - SPI2_MOSI : PB15 -For mode details please refer to `STM32L1DISCOVERY board User Manual`_. +For more details please refer to `STM32L1DISCOVERY board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/stm32l476g_disco/doc/index.rst b/boards/arm/stm32l476g_disco/doc/index.rst index bd4b2a5a6d5a5b9..65eef57c609f9cc 100644 --- a/boards/arm/stm32l476g_disco/doc/index.rst +++ b/boards/arm/stm32l476g_disco/doc/index.rst @@ -135,7 +135,7 @@ Connections and IOs STM32L476G Discovery Board has 8 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32L476G Discovery board User Manual`_. +For more details please refer to `STM32L476G Discovery board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32l496g_disco/doc/index.rst b/boards/arm/stm32l496g_disco/doc/index.rst index 0bd31e72c38c0fd..e8bc81f092b9e8a 100644 --- a/boards/arm/stm32l496g_disco/doc/index.rst +++ b/boards/arm/stm32l496g_disco/doc/index.rst @@ -164,7 +164,7 @@ Connections and IOs STM32L496G Discovery Board has 8 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32L496G Discovery board User Manual`_. +For more details please refer to `STM32L496G Discovery board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32l4r9i_disco/doc/index.rst b/boards/arm/stm32l4r9i_disco/doc/index.rst index a8f7798f840d0a2..0f651e2b9ffc254 100644 --- a/boards/arm/stm32l4r9i_disco/doc/index.rst +++ b/boards/arm/stm32l4r9i_disco/doc/index.rst @@ -71,7 +71,7 @@ The default configuration can be found in the defconfig file: Pin Mapping =========== -For mode details, please refer to `STM32L4R9I-DISCOVERY website`_. +For more details, please refer to `STM32L4R9I-DISCOVERY website`_. System Clock ============ diff --git a/boards/arm/stm32l562e_dk/doc/index.rst b/boards/arm/stm32l562e_dk/doc/index.rst index 5a4f5845617f15b..f3dd058b3419f85 100644 --- a/boards/arm/stm32l562e_dk/doc/index.rst +++ b/boards/arm/stm32l562e_dk/doc/index.rst @@ -251,7 +251,7 @@ Connections and IOs STM32L562E-DK Discovery Board has 8 GPIO controllers. These controllers are responsible for pin muxing, input/output, pull-up, etc. -For mode details please refer to `STM32L562E-DK Discovery board User Manual`_. +For more details please refer to `STM32L562E-DK Discovery board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi b/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi index 97263620f2e11ab..7c91d04cbb57eb6 100644 --- a/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi +++ b/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi @@ -111,16 +111,15 @@ stm32_lp_tick_source: &lptim1 { &spi1 { pinctrl-0 = <&spi1_sck_pg2 &spi1_miso_pg3 &spi1_mosi_pg4>; pinctrl-names = "default"; - cs-gpios = <&gpiog 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + cs-gpios = <&gpiog 5 GPIO_ACTIVE_LOW>; status = "okay"; spbtle-rf@0 { - compatible = "zephyr,bt-hci-spi", "st,hci-spi-v1"; + compatible = "st,hci-spi-v1"; reg = <0>; irq-gpios = <&gpiog 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; - reset-gpios = <&gpiog 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - spi-max-frequency = <2000000>; - controller-data-delay-us = <0>; /* No need for extra delay for BlueNRG-MS */ + reset-gpios = <&gpiog 8 GPIO_ACTIVE_LOW>; + spi-max-frequency = ; spi-hold-cs; }; }; diff --git a/boards/arm/stm32u5a9j_dk/doc/index.rst b/boards/arm/stm32u5a9j_dk/doc/index.rst index 6e3e44c5942adf9..23859666df7abc5 100644 --- a/boards/arm/stm32u5a9j_dk/doc/index.rst +++ b/boards/arm/stm32u5a9j_dk/doc/index.rst @@ -92,7 +92,7 @@ The default configuration per core can be found in the defconfig file: Pin Mapping =========== -For mode details please refer to `STM32U5A9J-DK board User Manual`_. +For more details please refer to `STM32U5A9J-DK board User Manual`_. Default Zephyr Peripheral Mapping: ---------------------------------- diff --git a/boards/arm/stm32vl_disco/doc/index.rst b/boards/arm/stm32vl_disco/doc/index.rst index 006c8854bb4ab31..7819200bafb30e0 100644 --- a/boards/arm/stm32vl_disco/doc/index.rst +++ b/boards/arm/stm32vl_disco/doc/index.rst @@ -119,7 +119,7 @@ Default Zephyr Peripheral Mapping: - I2C2_SCL : PB10 - I2C2_SDA : PB11 -For mode details please refer to `STM32VLDISCOVERY board User Manual`_. +For more details please refer to `STM32VLDISCOVERY board User Manual`_. Programming and Debugging ************************* diff --git a/boards/arm/twr_kv58f220m/twr_kv58f220m.yaml b/boards/arm/twr_kv58f220m/twr_kv58f220m.yaml index 810d96c2ae602c6..6118c0c0b113283 100644 --- a/boards/arm/twr_kv58f220m/twr_kv58f220m.yaml +++ b/boards/arm/twr_kv58f220m/twr_kv58f220m.yaml @@ -6,7 +6,7 @@ toolchain: - zephyr - gnuarmemb - xtools -ram: 256 +ram: 128 flash: 1024 supported: - i2c diff --git a/boards/arm/ucans32k1sic/Kconfig.defconfig b/boards/arm/ucans32k1sic/Kconfig.defconfig index 88941a6f64a51b8..044df50c0c592f4 100644 --- a/boards/arm/ucans32k1sic/Kconfig.defconfig +++ b/boards/arm/ucans32k1sic/Kconfig.defconfig @@ -13,4 +13,11 @@ config UART_CONSOLE endif # SERIAL +if CAN + +config GPIO + default y + +endif # CAN + endif # BOARD_UCANS32K1SIC diff --git a/boards/arm/ucans32k1sic/doc/index.rst b/boards/arm/ucans32k1sic/doc/index.rst index 1291eeb98904604..adceb43de036b91 100644 --- a/boards/arm/ucans32k1sic/doc/index.rst +++ b/boards/arm/ucans32k1sic/doc/index.rst @@ -49,6 +49,8 @@ GPIO on-chip gpio LPUART on-chip serial LPI2C on-chip i2c LPSPI on-chip spi +FTM on-chip pwm +FlexCAN on-chip can ============ ========== ================================ The default configuration can be found in the Kconfig file @@ -67,15 +69,30 @@ children nodes with the desired pinmux configuration to the singleton node LEDs ---- -The UCANS32K1SIC board has one user RGB LED: - -======================= ============== ===== -Devicetree node Label Pin -======================= ============== ===== -led0 / led1_red LED1_RGB_RED PTD15 -led1 / led1_green LED1_RGB_GREEN PTD16 -led2 / led1_blue LED1_RGB_BLUE PTD0 -======================= ============== ===== +The UCANS32K1SIC board has one user RGB LED that can be used either as a GPIO +LED or as a PWM LED. + +.. table:: RGB LED as GPIO LED + :widths: auto + + =============== ================ =============== ===== + Devicetree node Devicetree alias Label Pin + =============== ================ =============== ===== + led1_red led0 LED1_RGB_RED PTD15 + led1_green led1 LED1_RGB_GREEN PTD16 + led1_blue led2 LED1_RGB_BLUE PTD0 + =============== ================ =============== ===== + +.. table:: RGB LED as PWM LED + :widths: auto + + =============== ======================== ================== ================ + Devicetree node Devicetree alias Label Pin + =============== ======================== ================== ================ + led1_red_pwm pwm-led0 / red-pwm-led LED1_RGB_RED_PWM PTD15 / FTM0_CH0 + led1_green_pwm pwm-led1 / green-pwm-led LED1_RGB_GREEN_PWM PTD16 / FTM0_CH1 + led1_blue_pwm pwm-led2 / blue-pwm-led LED1_RGB_BLUE_PWM PTD0 / FTM0_CH2 + =============== ======================== ================== ================ The user can control the LEDs in any way. An output of ``0`` illuminates the LED. diff --git a/boards/arm/ucans32k1sic/ucans32k1sic-pinctrl.dtsi b/boards/arm/ucans32k1sic/ucans32k1sic-pinctrl.dtsi index d3926d9866e987b..2bb216e63aedcc6 100644 --- a/boards/arm/ucans32k1sic/ucans32k1sic-pinctrl.dtsi +++ b/boards/arm/ucans32k1sic/ucans32k1sic-pinctrl.dtsi @@ -37,4 +37,41 @@ drive-strength = "low"; }; }; + + ftm0_default: ftm0_default { + group0 { + pinmux = , + , + ; + drive-strength = "low"; + }; + }; + + ftm1_default: ftm1_default { + group0 { + pinmux = ; + drive-strength = "low"; + }; + }; + + ftm2_default: ftm2_default { + group0 { + pinmux = ; + drive-strength = "low"; + }; + }; + + flexcan0_default: flexcan0_default { + group0 { + pinmux = , ; + drive-strength = "low"; + }; + }; + + flexcan1_default: flexcan1_default { + group0 { + pinmux = , ; + drive-strength = "low"; + }; + }; }; diff --git a/boards/arm/ucans32k1sic/ucans32k1sic.dts b/boards/arm/ucans32k1sic/ucans32k1sic.dts index 49b30d168e28612..6996a12d6d006f5 100644 --- a/boards/arm/ucans32k1sic/ucans32k1sic.dts +++ b/boards/arm/ucans32k1sic/ucans32k1sic.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include +#include #include #include "ucans32k1sic-pinctrl.dtsi" @@ -20,12 +21,20 @@ zephyr,console = &lpuart1; zephyr,shell-uart = &lpuart1; zephyr,uart-pipe = &lpuart1; + zephyr,canbus = &flexcan0; }; aliases { led0 = &led1_red; led1 = &led1_green; led2 = &led1_blue; + pwm-led0 = &led1_red_pwm; + pwm-led1 = &led1_green_pwm; + pwm-led2 = &led1_blue_pwm; + red-pwm-led = &led1_red_pwm; + green-pwm-led = &led1_green_pwm; + blue-pwm-led = &led1_blue_pwm; + pwm-0 = &ftm0; sw0 = &button_3; i2c-0 = &lpi2c0; }; @@ -47,6 +56,23 @@ }; }; + pwmleds { + compatible = "pwm-leds"; + + led1_red_pwm: led_pwm_0 { + pwms = <&ftm0 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + label = "LED1_RGB_RED_PWM"; + }; + led1_green_pwm: led_pwm_1 { + pwms = <&ftm0 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + label = "LED1_RGB_GREEN_PWM"; + }; + led1_blue_pwm: led_pwm_2 { + pwms = <&ftm0 2 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + label = "LED1_RGB_BLUE_PWM"; + }; + }; + gpio_keys { compatible = "gpio-keys"; @@ -56,6 +82,20 @@ zephyr,code = ; }; }; + + can_phy0: can-phy0 { + compatible = "nxp,tja1463", "nxp,tja1443", "nxp,tja1153", "can-transceiver-gpio"; + enable-gpios = <&gpioa 10 GPIO_ACTIVE_HIGH>; + max-bitrate = <8000000>; + #phy-cells = <0>; + }; + + can_phy1: can-phy1 { + compatible = "nxp,tja1463", "nxp,tja1443", "nxp,tja1153", "can-transceiver-gpio"; + enable-gpios = <&gpioe 2 GPIO_ACTIVE_HIGH>; + max-bitrate = <8000000>; + #phy-cells = <0>; + }; }; &gpioa { @@ -104,3 +144,50 @@ pinctrl-names = "default"; status = "okay"; }; + +&ftm0 { + compatible = "nxp,kinetis-ftm-pwm"; + pinctrl-0 = <&ftm0_default>; + pinctrl-names = "default"; + prescaler = <128>; + #pwm-cells = <3>; + status = "okay"; +}; + +&ftm1 { + compatible = "nxp,kinetis-ftm-pwm"; + pinctrl-0 = <&ftm1_default>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "okay"; +}; + +&ftm2 { + compatible = "nxp,kinetis-ftm-pwm"; + pinctrl-0 = <&ftm2_default>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "okay"; +}; + +&flexcan0 { + pinctrl-0 = <&flexcan0_default>; + pinctrl-names = "default"; + phys = <&can_phy0>; + bus-speed = <125000>; + sample-point = <875>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + status = "okay"; +}; + +&flexcan1 { + pinctrl-0 = <&flexcan1_default>; + pinctrl-names = "default"; + phys = <&can_phy1>; + bus-speed = <125000>; + sample-point = <875>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + status = "okay"; +}; diff --git a/boards/arm/ucans32k1sic/ucans32k1sic.yaml b/boards/arm/ucans32k1sic/ucans32k1sic.yaml index 8519980aa60a0a8..d4bf0d5065c5284 100644 --- a/boards/arm/ucans32k1sic/ucans32k1sic.yaml +++ b/boards/arm/ucans32k1sic/ucans32k1sic.yaml @@ -17,3 +17,5 @@ supported: - pinctrl - i2c - spi + - pwm + - can diff --git a/boards/arm/v2m_beetle/doc/index.rst b/boards/arm/v2m_beetle/doc/index.rst index 80e7af563fca3a4..7673e510ebfae6c 100644 --- a/boards/arm/v2m_beetle/doc/index.rst +++ b/boards/arm/v2m_beetle/doc/index.rst @@ -190,7 +190,7 @@ Peripheral Mapping: - I2C_1_SDA : D22 - I2C_1_SCL : D23 -For mode details please refer to `Beetle Technical Reference Manual (TRM)`_. +For more details please refer to `Beetle Technical Reference Manual (TRM)`_. System Clock ============ diff --git a/boards/arm/v2m_musca_b1/doc/index.rst b/boards/arm/v2m_musca_b1/doc/index.rst index f36ae79dbb4a64b..0f0c261460a1009 100644 --- a/boards/arm/v2m_musca_b1/doc/index.rst +++ b/boards/arm/v2m_musca_b1/doc/index.rst @@ -205,7 +205,7 @@ Peripheral Mapping: - I2C_0_SDA : D14 - I2C_0_SCL : D15 -For mode details please refer to `Musca B1 Technical Reference Manual (TRM)`_. +For more details please refer to `Musca B1 Technical Reference Manual (TRM)`_. RGB LED diff --git a/boards/arm/v2m_musca_s1/doc/index.rst b/boards/arm/v2m_musca_s1/doc/index.rst index 4c8f4fcc0c114cf..8a1c4b221bd4957 100644 --- a/boards/arm/v2m_musca_s1/doc/index.rst +++ b/boards/arm/v2m_musca_s1/doc/index.rst @@ -199,7 +199,7 @@ Peripheral Mapping: - I2C_0_SDA : D14 - I2C_0_SCL : D15 -For mode details please refer to `Musca-S1 Technical Reference Manual (TRM)`_. +For more details please refer to `Musca-S1 Technical Reference Manual (TRM)`_. RGB LED diff --git a/boards/arm/xmc45_relax_kit/Kconfig.defconfig b/boards/arm/xmc45_relax_kit/Kconfig.defconfig index e6f0add4859f245..0296bc64ff79c5c 100644 --- a/boards/arm/xmc45_relax_kit/Kconfig.defconfig +++ b/boards/arm/xmc45_relax_kit/Kconfig.defconfig @@ -8,4 +8,15 @@ if BOARD_XMC45_RELAX_KIT config BOARD default "xmc45_relax_kit" +if NETWORKING + +config NET_L2_ETHERNET + default y +config MDIO + default y +config TEST_RANDOM_GENERATOR + default y + +endif # NETWORKING + endif # BOARD_XMC45_RELAX_KIT diff --git a/boards/arm/xmc45_relax_kit/doc/index.rst b/boards/arm/xmc45_relax_kit/doc/index.rst index 7a54abfe37ad52d..6d75146046ea5e9 100644 --- a/boards/arm/xmc45_relax_kit/doc/index.rst +++ b/boards/arm/xmc45_relax_kit/doc/index.rst @@ -57,6 +57,12 @@ The Relax Kit development board configuration supports the following hardware fe +-----------+------------+-----------------------+ | WATCHDOG | on-chip | watchdog | +-----------+------------+-----------------------+ +| MDIO | on-chip | mdio | ++-----------+------------+-----------------------+ +| ETHERNET | on-chip | ethernet | ++-----------+------------+-----------------------+ +| PTP | on-chip | ethernet | ++-----------+------------+-----------------------+ More details about the supported peripherals are available in `XMC4500 TRM`_ Other hardware features are not currently supported by the Zephyr kernel. diff --git a/boards/arm/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi b/boards/arm/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi index 04156e2890ceb6b..936733ea02a83a8 100644 --- a/boards/arm/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi +++ b/boards/arm/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi @@ -27,3 +27,61 @@ drive-push-pull; hwctrl = "disabled"; }; + +ð_p2_0_mdo { + drive-strength = "strong-sharp-edge"; + output-low; +}; + +ð_p2_7_mdc { + drive-strength = "strong-medium-edge"; + drive-push-pull; + output-low; + hwctrl = "disabled"; +}; + +ð_p2_5_tx_en { + drive-strength = "strong-medium-edge"; + drive-push-pull; + output-low; + hwctrl = "disabled"; +}; + +ð_p2_8_txd0 { + drive-strength = "strong-medium-edge"; + drive-push-pull; + output-low; + hwctrl = "disabled"; +}; + +ð_p2_9_txd1 { + drive-strength = "strong-medium-edge"; + drive-push-pull; + output-low; + hwctrl = "disabled"; +}; + +ð_p2_4_rxer { + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; + +ð_p2_2_rxd0{ + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; + +ð_p2_3_rxd1 { + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; + +ð_p15_8_clk_rmii { + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; + +ð_p15_9_crs_dv { + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; diff --git a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts index cebeb2deffe5e61..6b1519a455383d6 100644 --- a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts +++ b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts @@ -133,3 +133,32 @@ pinctrl-0 = <&pwm_out_p1_0_ccu40_ch3 &pwm_out_p1_1_ccu40_ch2>; pinctrl-names = "default"; }; + +ð { + status = "okay"; + pinctrl-0 = <ð_p2_4_rxer ð_p2_2_rxd0 ð_p2_3_rxd1 + ð_p15_8_clk_rmii ð_p15_9_crs_dv ð_p2_5_tx_en + ð_p2_8_txd0 ð_p2_9_txd1>; + pinctrl-names = "default"; + + rxer-port-ctrl = "P2_4"; + rxd0-port-ctrl = "P2_2"; + rxd1-port-ctrl = "P2_3"; + rmii-rx-clk-port-ctrl = "P15_8"; + crs-rx-dv-port-ctrl = "P15_9"; + + phy-connection-type = "rmii"; + phy-handle = <&phy>; +}; + +&mdio { + status = "okay"; + mdi-port-ctrl = "P2_0"; + pinctrl-0 = <ð_p2_0_mdo ð_p2_7_mdc>; + pinctrl-names = "default"; + + phy: ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0>; + }; +}; diff --git a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.yaml b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.yaml index b84e29973a7b7a2..031d9dc5a6c22fe 100644 --- a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.yaml +++ b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.yaml @@ -13,6 +13,7 @@ supported: - spi - uart - watchdog + - netif:eth ram: 160 flash: 1024 vendor: infineon diff --git a/boards/arm/xmc47_relax_kit/Kconfig.defconfig b/boards/arm/xmc47_relax_kit/Kconfig.defconfig index da18e0230b1d746..98978ffd5409df4 100644 --- a/boards/arm/xmc47_relax_kit/Kconfig.defconfig +++ b/boards/arm/xmc47_relax_kit/Kconfig.defconfig @@ -7,4 +7,15 @@ if BOARD_XMC47_RELAX_KIT config BOARD default "xmc47_relax_kit" +if NETWORKING + +config NET_L2_ETHERNET + default y +config MDIO + default y +config TEST_RANDOM_GENERATOR + default y + +endif # NETWORKING + endif diff --git a/boards/arm/xmc47_relax_kit/doc/index.rst b/boards/arm/xmc47_relax_kit/doc/index.rst index cbf5eb7a5f34c8f..8fb2ce9997ad5e7 100644 --- a/boards/arm/xmc47_relax_kit/doc/index.rst +++ b/boards/arm/xmc47_relax_kit/doc/index.rst @@ -60,6 +60,12 @@ The Relax Kit development board configuration supports the following hardware fe +-----------+------------+-----------------------+ | WATCHDOG | on-chip | watchdog | +-----------+------------+-----------------------+ +| MDIO | on-chip | mdio | ++-----------+------------+-----------------------+ +| ETHERNET | on-chip | ethernet | ++-----------+------------+-----------------------+ +| PTP | on-chip | ethernet | ++-----------+------------+-----------------------+ More details about the supported peripherals are available in `XMC4700 TRM`_ Other hardware features are not currently supported by the Zephyr kernel. diff --git a/boards/arm/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi b/boards/arm/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi index 83d92d7ee51068c..c81e1222cf8c884 100644 --- a/boards/arm/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi +++ b/boards/arm/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi @@ -67,3 +67,61 @@ drive-open-drain; hwctrl = "disabled"; }; + +ð_p2_0_mdo { + drive-strength = "strong-sharp-edge"; + output-low; +}; + +ð_p2_7_mdc { + drive-strength = "strong-medium-edge"; + drive-push-pull; + output-low; + hwctrl = "disabled"; +}; + +ð_p2_5_tx_en { + drive-strength = "strong-medium-edge"; + drive-push-pull; + output-low; + hwctrl = "disabled"; +}; + +ð_p2_8_txd0 { + drive-strength = "strong-medium-edge"; + drive-push-pull; + output-low; + hwctrl = "disabled"; +}; + +ð_p2_9_txd1 { + drive-strength = "strong-medium-edge"; + drive-push-pull; + output-low; + hwctrl = "disabled"; +}; + +ð_p2_4_rxer { + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; + +ð_p2_2_rxd0{ + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; + +ð_p2_3_rxd1 { + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; + +ð_p15_8_clk_rmii { + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; + +ð_p15_9_crs_dv { + drive-strength = "strong-medium-edge"; + hwctrl = "disabled"; +}; diff --git a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts index 7f1b8f68a3864d3..a9e0731fa0e7415 100644 --- a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts +++ b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts @@ -48,7 +48,7 @@ }; chosen { - zephyr,sram = &psram1; + zephyr,sram = &dsram_joined; zephyr,flash = &flash0; zephyr,console = &usic0ch0; zephyr,shell-uart = &usic0ch0; @@ -58,14 +58,9 @@ }; -&dsram1 { +&psram1 { compatible = "zephyr,memory-region", "mmio-sram"; - zephyr,memory-region = "DSRAM1"; -}; - -&dsram2 { - compatible = "zephyr,memory-region", "mmio-sram"; - zephyr,memory-region = "DSRAM2"; + zephyr,memory-region = "PSRAM1"; }; &cpu0 { @@ -175,3 +170,32 @@ pinctrl-0 = <&pwm_out_p5_9_ccu80_ch4_high &pwm_out_p5_8_ccu80_ch0_low>; pinctrl-names = "default"; }; + +ð { + status = "okay"; + pinctrl-0 = <ð_p2_4_rxer ð_p2_2_rxd0 ð_p2_3_rxd1 + ð_p15_8_clk_rmii ð_p15_9_crs_dv ð_p2_5_tx_en + ð_p2_8_txd0 ð_p2_9_txd1>; + pinctrl-names = "default"; + + rxer-port-ctrl = "P2_4"; + rxd0-port-ctrl = "P2_2"; + rxd1-port-ctrl = "P2_3"; + rmii-rx-clk-port-ctrl = "P15_8"; + crs-rx-dv-port-ctrl = "P15_9"; + + phy-connection-type = "rmii"; + phy-handle = <&phy>; +}; + +&mdio { + status = "okay"; + mdi-port-ctrl = "P2_0"; + pinctrl-0 = <ð_p2_0_mdo ð_p2_7_mdc>; + pinctrl-names = "default"; + + phy: ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0>; + }; +}; diff --git a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml index d88826ab4ef0038..72fa356ef0cb0e2 100644 --- a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml +++ b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml @@ -15,6 +15,7 @@ supported: - arduino_spi - arduino_serial - watchdog + - netif:eth ram: 352 flash: 2048 vendor: infineon diff --git a/boards/arm64/mimx93_evk/mimx93_evk-pinctrl.dtsi b/boards/arm64/mimx93_evk/mimx93_evk-pinctrl.dtsi index 83070adf93fde9b..31e35907f86d6ad 100644 --- a/boards/arm64/mimx93_evk/mimx93_evk-pinctrl.dtsi +++ b/boards/arm64/mimx93_evk/mimx93_evk-pinctrl.dtsi @@ -26,4 +26,61 @@ drive-strength = "x5"; }; }; + + i2c1_default: i2c1_default { + group0 { + pinmux = <&iomuxc1_i2c1_scl_lpi2c_scl_lpi2c1_scl>, + <&iomuxc1_i2c1_sda_lpi2c_sda_lpi2c1_sda>; + drive-strength = "x5"; + drive-open-drain; + slew-rate = "fast"; + input-enable; + }; + }; + + i2c2_default: i2c2_default { + group0 { + pinmux = <&iomuxc1_i2c2_scl_lpi2c_scl_lpi2c2_scl>, + <&iomuxc1_i2c2_sda_lpi2c_sda_lpi2c2_sda>; + drive-strength = "x5"; + drive-open-drain; + slew-rate = "fast"; + input-enable; + }; + }; + + i2c3_default: i2c3_default { + group0 { + pinmux = <&iomuxc1_gpio_io01_lpi2c_scl_lpi2c3_scl>, + <&iomuxc1_gpio_io00_lpi2c_sda_lpi2c3_sda>; + drive-strength = "x5"; + drive-open-drain; + slew-rate = "fast"; + input-enable; + }; + }; + + i2c4_default: i2c4_default { + group0 { + pinmux = <&iomuxc1_gpio_io03_lpi2c_scl_lpi2c4_scl>, + <&iomuxc1_gpio_io02_lpi2c_sda_lpi2c4_sda>; + drive-strength = "x5"; + drive-open-drain; + slew-rate = "fast"; + input-enable; + }; + }; + + spi3_default: spi3_default { + group0 { + pinmux = <&iomuxc1_gpio_io07_lpspi_pcs_lpspi3_pcs1>, + <&iomuxc1_gpio_io08_lpspi_pcs_lpspi3_pcs0>, + <&iomuxc1_gpio_io09_lpspi_sin_lpspi3_sin>, + <&iomuxc1_gpio_io10_lpspi_sout_lpspi3_sout>, + <&iomuxc1_gpio_io11_lpspi_sck_lpspi3_sck>; + slew-rate = "fast"; + drive-strength = "x5"; + }; + }; + }; diff --git a/boards/arm64/mimx93_evk/mimx93_evk_a55.dts b/boards/arm64/mimx93_evk/mimx93_evk_a55.dts index 375bb2f7a0ef15a..2fb9d0e9c123769 100644 --- a/boards/arm64/mimx93_evk/mimx93_evk_a55.dts +++ b/boards/arm64/mimx93_evk/mimx93_evk_a55.dts @@ -45,3 +45,25 @@ pinctrl-0 = <&uart2_default>; pinctrl-names = "default"; }; + + +&lpi2c1{ + status = "disabled"; + clock-frequency = ; + pinctrl-0 = <&i2c1_default>; + pinctrl-names = "default"; +}; + +&lpi2c2{ + status = "disabled"; + clock-frequency = ; + pinctrl-0 = <&i2c2_default>; + pinctrl-names = "default"; +}; + +&lpspi3 { + status = "disabled"; + clock-frequency = <1000000>; + pinctrl-0 = <&spi3_default>; + pinctrl-names = "default"; +}; diff --git a/boards/arm64/mimx93_evk/mimx93_evk_a55.yaml b/boards/arm64/mimx93_evk/mimx93_evk_a55.yaml index 72e4c677fc0c729..a57ec92ea4f7ab2 100644 --- a/boards/arm64/mimx93_evk/mimx93_evk_a55.yaml +++ b/boards/arm64/mimx93_evk/mimx93_evk_a55.yaml @@ -6,6 +6,10 @@ toolchain: - zephyr - cross-compile ram: 1024 +supported: + - uart + - i2c + - spi testing: ignore_tags: - net diff --git a/boards/common/linkserver.board.cmake b/boards/common/linkserver.board.cmake index 743eef573994ba5..74de78449c6d6c7 100644 --- a/boards/common/linkserver.board.cmake +++ b/boards/common/linkserver.board.cmake @@ -1,4 +1,6 @@ # Copyright 2023 NXP # SPDX-License-Identifier: Apache-2.0 +board_set_flasher_ifnset(linkserver) +board_set_debugger_ifnset(linkserver) board_finalize_runner_args(linkserver "--dt-flash=y") diff --git a/boards/posix/native_sim/doc/index.rst b/boards/posix/native_sim/doc/index.rst index be4197056438b53..64579fc4631a934 100644 --- a/boards/posix/native_sim/doc/index.rst +++ b/boards/posix/native_sim/doc/index.rst @@ -433,10 +433,17 @@ The following peripherals are currently provided with this board: .. _nsim_per_flash_simu: -**Flash driver** - A flash driver is provided that accesses all flash data through a binary file - on the host file system. The behavior of the flash device can be configured - through the native_sim board devicetree or Kconfig settings under +**EEPROM simulator** + The EEPROM simulator can also be used in the native targets. In these, you have the added feature + of keeping the EEPROM content on a file on the host filesystem. + By default this is kept in the file :file:`eeprom.bin` in the current working directory, but you + can select the location of this file and its name with the command line parameter ``--eeprom``. + Some more information can be found in :ref:`the emulators page `. + +**Flash simulator** + The flash simulator can also be used in the native targets. In this you have the option to keep + the flash content in a binary file on the host file system or in RAM. The behavior of the flash + device can be configured through the native_sim board devicetree or Kconfig settings under :kconfig:option:`CONFIG_FLASH_SIMULATOR`. By default the binary data is located in the file :file:`flash.bin` in the current @@ -446,25 +453,43 @@ The following peripherals are currently provided with this board: configuration. In case the file does not exists the driver will take care of creating the file, else the existing file is used. + Some more information can be found in :ref:`the emulators page `. + The flash content can be accessed from the host system, as explained in the `Host based flash access`_ section. **Input events** - A driver is provided to read input events from a Linux evdev input device and - inject them back into the Zephyr input subsystem. + Two optional native input drivers are available: + + **evdev driver** + A driver is provided to read input events from a Linux evdev input device and + inject them back into the Zephyr input subsystem. + + The driver is automatically enabled when :kconfig:option:`CONFIG_INPUT` is + enabled and the devicetree contains a node such as: + + .. code-block:: dts + + evdev { + compatible = "zephyr,native-linux-evdev"; + }; - The driver is automatically enabled when :kconfig:option:`CONFIG_INPUT` is - enabled and the devicetree contains a node such as: + The application then has to be run with a command line option to specify + which evdev device node has to be used, for example + ``zephyr.exe --evdev=/dev/input/event0``. - .. code-block:: dts + **Input SDL touch** + This driver emulates a touch panel input using the SDL library. It can be enabled with + :kconfig:option:`CONFIG_INPUT_SDL_TOUCH` and configured with the device tree binding + :dtcompatible:`zephyr,input-sdl-touch`. - evdev { - compatible = "zephyr,native-linux-evdev"; - }; + More information on using SDL and the Display driver can be found in + :ref:`its section `. - The application then has to be run with a command line option to specify - which evdev device node has to be used, for example - ``zephyr.exe --evdev=/dev/input/event0``. +**CAN controller** + It is possible to use a host CAN controller with the native SockerCAN Linux driver. It can be + enabled with :kconfig:option:`CONFIG_CAN_NATIVE_LINUX` and configured with the device tree binding + :dtcompatible:`zephyr,native-linux-can`. .. _native_ptty_uart: @@ -654,27 +679,27 @@ host libC (:kconfig:option:`CONFIG_EXTERNAL_LIBC`): .. csv-table:: Drivers/backends vs libC choice :header: Driver class, driver name, driver kconfig, libC choices - adc, ADC emul, :kconfig:option:`CONFIG_ADC_EMUL`, all - bluetooth, :ref:`userchan `, :kconfig:option:`CONFIG_BT_USERCHAN`, host libC - can, can native Linux, :kconfig:option:`CONFIG_CAN_NATIVE_LINUX`, all - console backend, :ref:`POSIX arch console `, :kconfig:option:`CONFIG_POSIX_ARCH_CONSOLE`, all - display, :ref:`display SDL `, :kconfig:option:`CONFIG_SDL_DISPLAY`, all - entropy, :ref:`native posix entropy `, :kconfig:option:`CONFIG_FAKE_ENTROPY_NATIVE_POSIX`, all - eeprom, eeprom simulator, :kconfig:option:`CONFIG_EEPROM_SIMULATOR`, host libC - eeprom, eeprom emulator, :kconfig:option:`CONFIG_EEPROM_EMULATOR`, all - ethernet, :ref:`eth native_posix `, :kconfig:option:`CONFIG_ETH_NATIVE_POSIX`, all - flash, :ref:`flash simulator `, :kconfig:option:`CONFIG_FLASH_SIMULATOR`, all - flash, :ref:`host based flash access `, :kconfig:option:`CONFIG_FUSE_FS_ACCESS`, host libC - gpio, GPIO emulator, :kconfig:option:`CONFIG_GPIO_EMUL`, all - gpio, SDL GPIO emulator, :kconfig:option:`CONFIG_GPIO_EMUL_SDL`, all - i2c, I2C emulator, :kconfig:option:`CONFIG_I2C_EMUL`, all - input, input SDL touch, :kconfig:option:`CONFIG_INPUT_SDL_TOUCH`, all - input, Linux evdev, :kconfig:option:`CONFIG_NATIVE_LINUX_EVDEV`, all - log backend, :ref:`native backend `, :kconfig:option:`CONFIG_LOG_BACKEND_NATIVE_POSIX`, all - rtc, RTC emul, :kconfig:option:`CONFIG_RTC_EMUL`, all - serial, :ref:`uart native posix/PTTY `, :kconfig:option:`CONFIG_UART_NATIVE_POSIX`, all - serial, :ref:`uart native TTY `, :kconfig:option:`CONFIG_UART_NATIVE_TTY`, all - spi, SPI emul, :kconfig:option:`CONFIG_SPI_EMUL`, all - system tick, native_posix timer, :kconfig:option:`CONFIG_NATIVE_POSIX_TIMER`, all - tracing, :ref:`Posix tracing backend `, :kconfig:option:`CONFIG_TRACING_BACKEND_POSIX`, all - usb, :ref:`USB native posix `, :kconfig:option:`CONFIG_USB_NATIVE_POSIX`, host libC + ADC, ADC emul, :kconfig:option:`CONFIG_ADC_EMUL`, All + Bluetooth, :ref:`Userchan `, :kconfig:option:`CONFIG_BT_USERCHAN`, Host libC + CAN, CAN native Linux, :kconfig:option:`CONFIG_CAN_NATIVE_LINUX`, All + Console backend, :ref:`POSIX arch console `, :kconfig:option:`CONFIG_POSIX_ARCH_CONSOLE`, All + Display, :ref:`Display SDL `, :kconfig:option:`CONFIG_SDL_DISPLAY`, All + Entropy, :ref:`Native posix entropy `, :kconfig:option:`CONFIG_FAKE_ENTROPY_NATIVE_POSIX`, All + EEPROM, EEPROM simulator, :kconfig:option:`CONFIG_EEPROM_SIMULATOR`, Host libC + EEPROM, EEPROM emulator, :kconfig:option:`CONFIG_EEPROM_EMULATOR`, All + Ethernet, :ref:`Eth native_posix `, :kconfig:option:`CONFIG_ETH_NATIVE_POSIX`, All + Flash, :ref:`Flash simulator `, :kconfig:option:`CONFIG_FLASH_SIMULATOR`, All + Flash, :ref:`Host based flash access `, :kconfig:option:`CONFIG_FUSE_FS_ACCESS`, Host libC + GPIO, GPIO emulator, :kconfig:option:`CONFIG_GPIO_EMUL`, All + GPIO, SDL GPIO emulator, :kconfig:option:`CONFIG_GPIO_EMUL_SDL`, All + I2C, I2C emulator, :kconfig:option:`CONFIG_I2C_EMUL`, All + Input, Input SDL touch, :kconfig:option:`CONFIG_INPUT_SDL_TOUCH`, All + Input, Linux evdev, :kconfig:option:`CONFIG_NATIVE_LINUX_EVDEV`, All + Logger backend, :ref:`Native backend `, :kconfig:option:`CONFIG_LOG_BACKEND_NATIVE_POSIX`, All + RTC, RTC emul, :kconfig:option:`CONFIG_RTC_EMUL`, All + Serial, :ref:`UART native posix/PTTY `, :kconfig:option:`CONFIG_UART_NATIVE_POSIX`, All + Serial, :ref:`UART native TTY `, :kconfig:option:`CONFIG_UART_NATIVE_TTY`, All + SPI, SPI emul, :kconfig:option:`CONFIG_SPI_EMUL`, All + System tick, Native_posix timer, :kconfig:option:`CONFIG_NATIVE_POSIX_TIMER`, All + Tracing, :ref:`Posix tracing backend `, :kconfig:option:`CONFIG_TRACING_BACKEND_POSIX`, All + USB, :ref:`USB native posix `, :kconfig:option:`CONFIG_USB_NATIVE_POSIX`, Host libC diff --git a/boards/posix/nrf_bsim/Kconfig b/boards/posix/nrf_bsim/Kconfig index 7d67c44d284a350..d86478a4f4c9c7b 100644 --- a/boards/posix/nrf_bsim/Kconfig +++ b/boards/posix/nrf_bsim/Kconfig @@ -17,19 +17,25 @@ endif # SOC_SERIES_BSIM_NRFXX config SOC_SERIES_BSIM_NRFXX bool - depends on SOC_POSIX + select NATIVE_LIBRARY + select SOC_COMPATIBLE_NRF + select HAS_NRFX + select HAS_NORDIC_DRIVERS + select PINCTRL_DYNAMIC if PINCTRL help Any NRF simulated SOC with BabbleSim, based on the POSIX arch config SOC_SERIES_BSIM_NRF52X bool - depends on SOC_SERIES_BSIM_NRFXX + select SOC_SERIES_BSIM_NRFXX + select SOC_COMPATIBLE_NRF52X help Any NRF52 simulated SOC with BabbleSim, based on the POSIX arch config SOC_SERIES_BSIM_NRF53X bool - depends on SOC_SERIES_BSIM_NRFXX + select SOC_SERIES_BSIM_NRFXX + select SOC_COMPATIBLE_NRF53X help Any NRF53 simulated SOC with BabbleSim, based on the POSIX arch diff --git a/boards/posix/nrf_bsim/Kconfig.board b/boards/posix/nrf_bsim/Kconfig.board index 4a701c9acdc5d79..fcfbae4d4e762af 100644 --- a/boards/posix/nrf_bsim/Kconfig.board +++ b/boards/posix/nrf_bsim/Kconfig.board @@ -2,48 +2,30 @@ config BOARD_NRF52_BSIM bool "NRF52 simulation model" - select SOC_SERIES_BSIM_NRFXX select SOC_SERIES_BSIM_NRF52X - select SOC_COMPATIBLE_NRF - select SOC_COMPATIBLE_NRF52X select SOC_COMPATIBLE_NRF52833 select NRF_RTC_TIMER select CLOCK_CONTROL - select HAS_NRFX - select HAS_NORDIC_DRIVERS - select NATIVE_LIBRARY help Will produce a console Linux process which can be executed natively. It needs the BabbleSim simulator both in compile time and to execute config BOARD_NRF5340BSIM_NRF5340_CPUNET bool "Simulated NRF53 Network core" - select SOC_SERIES_BSIM_NRFXX select SOC_SERIES_BSIM_NRF53X - select SOC_COMPATIBLE_NRF - select SOC_COMPATIBLE_NRF53X select SOC_COMPATIBLE_NRF5340_CPUNET select NRF_RTC_TIMER select CLOCK_CONTROL - select HAS_NRFX - select HAS_NORDIC_DRIVERS - select NATIVE_LIBRARY help Will produce a console Linux process which can be executed natively. It needs the BabbleSim simulator both in compile time and to execute config BOARD_NRF5340BSIM_NRF5340_CPUAPP bool "Simulated NRF53 Application core" - select SOC_SERIES_BSIM_NRFXX select SOC_SERIES_BSIM_NRF53X - select SOC_COMPATIBLE_NRF - select SOC_COMPATIBLE_NRF53X select SOC_COMPATIBLE_NRF5340_CPUAPP select NRF_RTC_TIMER select CLOCK_CONTROL - select HAS_NRFX - select HAS_NORDIC_DRIVERS - select NATIVE_LIBRARY help Will produce a console Linux process which can be executed natively. It needs the BabbleSim simulator both in compile time and to execute diff --git a/boards/posix/nrf_bsim/Kconfig.defconfig b/boards/posix/nrf_bsim/Kconfig.defconfig index e762a3c6c85c29b..d4e48ada7ad3b86 100644 --- a/boards/posix/nrf_bsim/Kconfig.defconfig +++ b/boards/posix/nrf_bsim/Kconfig.defconfig @@ -87,10 +87,7 @@ endif # LOG if CONSOLE config POSIX_ARCH_CONSOLE - default y if !SERIAL - -config UART_CONSOLE - default y if SERIAL + default y endif # CONSOLE diff --git a/boards/posix/nrf_bsim/board_soc.h b/boards/posix/nrf_bsim/board_soc.h index 1b7e7a85c0cf1a3..d75a187aa610990 100644 --- a/boards/posix/nrf_bsim/board_soc.h +++ b/boards/posix/nrf_bsim/board_soc.h @@ -29,6 +29,7 @@ #include #include #include "cmsis.h" +#include "soc_nrf_common.h" #if defined(CONFIG_BOARD_NRF52_BSIM) #define OFFLOAD_SW_IRQ SWI0_EGU0_IRQn diff --git a/boards/posix/nrf_bsim/doc/nrf52_bsim.rst b/boards/posix/nrf_bsim/doc/nrf52_bsim.rst index da1212e33679301..78c8e5c327963e9 100644 --- a/boards/posix/nrf_bsim/doc/nrf52_bsim.rst +++ b/boards/posix/nrf_bsim/doc/nrf52_bsim.rst @@ -36,6 +36,7 @@ This board includes models of some of the nRF52 SOC peripherals: * RNG (Random Number Generator) * RTC (Real Time Counter) * TEMP (Temperature sensor) +* UART & UARTE (UART with Easy DMA) * UICR (User Information Configuration Registers) and will use the same drivers as the nrf52 dk targets for these. diff --git a/boards/posix/nrf_bsim/nrf52_bsim.dts b/boards/posix/nrf_bsim/nrf52_bsim.dts index a408ceb0eee3aaa..8410c80fb74974e 100644 --- a/boards/posix/nrf_bsim/nrf52_bsim.dts +++ b/boards/posix/nrf_bsim/nrf52_bsim.dts @@ -9,6 +9,8 @@ #include #include +/* We resuse the pinctrl definitions directly from the real board : */ +#include <../boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833-pinctrl.dtsi> / { model = "nrf52 bsim"; @@ -22,8 +24,6 @@ /delete-property/ spi-1; /delete-property/ spi-2; /delete-property/ spi-3; - /delete-property/ uart-0; - /delete-property/ uart-1; /delete-property/ adc-0; /delete-property/ wdt-0; /delete-property/ pwm-0; @@ -36,13 +36,15 @@ chosen { zephyr,ieee802154 = &ieee802154; zephyr,flash = &flash0; + /* UART used by the BT controller UART HCI driver by default: */ + zephyr,bt-c2h-uart = &uart1; + /* UART used by the BT host UART HCI driver by default: */ + zephyr,bt-uart = &uart1; }; soc { /delete-node/ memory@20000000; /delete-node/ adc@40007000; - /delete-node/ uart@40002000; - /delete-node/ uart@40028000; /delete-node/ i2c@40003000; /delete-node/ i2c@40004000; /delete-node/ pwm@4001c000; @@ -98,3 +100,22 @@ }; }; }; + +&uart0 { + compatible = "nordic,nrf-uarte"; + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart1 { + compatible = "nordic,nrf-uarte"; + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; + hw-flow-control; +}; diff --git a/boards/posix/nrf_bsim/nrf52_bsim_defconfig b/boards/posix/nrf_bsim/nrf52_bsim_defconfig index 42231465cea194f..953e8c1aa931e6d 100644 --- a/boards/posix/nrf_bsim/nrf52_bsim_defconfig +++ b/boards/posix/nrf_bsim/nrf52_bsim_defconfig @@ -4,3 +4,4 @@ CONFIG_SOC_POSIX=y CONFIG_BOARD_NRF52_BSIM=y CONFIG_CONSOLE=y CONFIG_NO_OPTIMIZATIONS=y +CONFIG_LOG_BACKEND_UART=n diff --git a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts index c5ec3c95af57155..72194f3b0e1b68f 100644 --- a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts +++ b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts @@ -18,17 +18,13 @@ /delete-property/ sram-0; /delete-property/ i2c-0; /delete-property/ spi-0; - /delete-property/ uart-0; /delete-property/ i2c-1; /delete-property/ spi-1; - /delete-property/ uart-1; /delete-property/ spi-4; /delete-property/ i2c-2; /delete-property/ spi-2; - /delete-property/ uart-2; /delete-property/ i2c-3; /delete-property/ spi-3; - /delete-property/ uart-3; /delete-property/ wdt-0; /delete-property/ wdt-1; /delete-property/ pwm-0; @@ -61,17 +57,13 @@ /delete-node/ ctrlap@6000; /delete-node/ i2c@8000; /delete-node/ spi@8000; - /delete-node/ uart@8000; /delete-node/ i2c@9000; /delete-node/ spi@9000; - /delete-node/ uart@9000; /delete-node/ spi@a000; /delete-node/ i2c@b000; /delete-node/ spi@b000; - /delete-node/ uart@b000; /delete-node/ i2c@c000; /delete-node/ spi@c000; - /delete-node/ uart@c000; /delete-node/ adc@e000; /delete-node/ watchdog@18000; /delete-node/ watchdog@19000; diff --git a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.dts b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.dts index d9d7b02fc673ba7..93e3ee271634e85 100644 --- a/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.dts +++ b/boards/posix/nrf_bsim/nrf5340bsim_nrf5340_cpunet.dts @@ -21,7 +21,6 @@ /delete-property/ wdt-0; /delete-property/ i2c-0; /delete-property/ spi-0; - /delete-property/ uart-0; /delete-property/ gpio-0; /delete-property/ gpio-1; }; @@ -41,7 +40,6 @@ /delete-node/ watchdog@4100b000; /delete-node/ i2c@41013000; /delete-node/ spi@41013000; - /delete-node/ uart@41013000; /delete-node/ acl@41080000; /delete-node/ vmc@41081000; /delete-node/ gpio@418c0500; diff --git a/boards/posix/nrf_bsim/soc/pinctrl_soc.h b/boards/posix/nrf_bsim/soc/pinctrl_soc.h new file mode 100644 index 000000000000000..08252b57feeff42 --- /dev/null +++ b/boards/posix/nrf_bsim/soc/pinctrl_soc.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BOARDS_POSIX_NRF_BSIM_SOC_PINCTRL_SOC_H +#define BOARDS_POSIX_NRF_BSIM_SOC_PINCTRL_SOC_H + +/* We reuse the real SOC's header: */ +#include "../soc/arm/nordic_nrf/common/pinctrl_soc.h" + +#endif /* BOARDS_POSIX_NRF_BSIM_SOC_PINCTRL_SOC_H */ diff --git a/boards/posix/nrf_bsim/soc/soc_nrf_common.h b/boards/posix/nrf_bsim/soc/soc_nrf_common.h new file mode 100644 index 000000000000000..a77778de6530b04 --- /dev/null +++ b/boards/posix/nrf_bsim/soc/soc_nrf_common.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BOARDS_POSIX_NRF_BSIM_SOC_SOC_NRF_COMMON_H +#define BOARDS_POSIX_NRF_BSIM_SOC_SOC_NRF_COMMON_H + +/* We reuse the real SOC's header: */ +#include "../soc/arm/nordic_nrf/common/soc_nrf_common.h" + +#endif /* BOARDS_POSIX_NRF_BSIM_SOC_SOC_NRF_COMMON_H */ diff --git a/boards/riscv/adp_xc7k_ae350/Kconfig.board b/boards/riscv/adp_xc7k_ae350/Kconfig.board index 085eb9696a8c4cd..5b58e01fbfdb6d3 100644 --- a/boards/riscv/adp_xc7k_ae350/Kconfig.board +++ b/boards/riscv/adp_xc7k_ae350/Kconfig.board @@ -3,4 +3,4 @@ config BOARD_ADP_XC7K_AE350 bool "Andes ADP-XC7K AE350 Platform" - depends on SOC_RISCV_ANDES_AE350 + depends on SOC_ANDES_AE350 diff --git a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350_defconfig b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350_defconfig index 3f7f1f727c6c0b9..edbe7118c643012 100644 --- a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350_defconfig +++ b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350_defconfig @@ -1,5 +1,5 @@ -CONFIG_SOC_SERIES_RISCV_ANDES_V5=y -CONFIG_SOC_RISCV_ANDES_AE350=y +CONFIG_SOC_SERIES_ANDES_AE350=y +CONFIG_SOC_ANDES_AE350=y CONFIG_BOARD_ADP_XC7K_AE350=y CONFIG_XIP=n CONFIG_CONSOLE=y diff --git a/boards/riscv/beaglev_fire/Kconfig.board b/boards/riscv/beaglev_fire/Kconfig.board index 1984bb05c0994ce..55b59d4ac922a63 100644 --- a/boards/riscv/beaglev_fire/Kconfig.board +++ b/boards/riscv/beaglev_fire/Kconfig.board @@ -3,7 +3,7 @@ config BOARD_BEAGLEV_FIRE bool "Beagleboard BeagleV-Fire" - depends on SOC_MPFS + depends on SOC_POLARFIRE select 64BIT select SCHED_IPI_SUPPORTED select CPU_HAS_FPU_DOUBLE_PRECISION diff --git a/boards/riscv/beaglev_fire/beaglev_fire_defconfig b/boards/riscv/beaglev_fire/beaglev_fire_defconfig index a60ed8c16915ef7..3b264d6c28809ad 100644 --- a/boards/riscv/beaglev_fire/beaglev_fire_defconfig +++ b/boards/riscv/beaglev_fire/beaglev_fire_defconfig @@ -1,8 +1,8 @@ # Copyright (c) 2023 Microchip Technology Inc # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV64_MIV=y -CONFIG_SOC_MPFS=y +CONFIG_SOC_SERIES_POLARFIRE=y +CONFIG_SOC_POLARFIRE=y CONFIG_MPFS_HAL=n CONFIG_BASE64=y CONFIG_INCLUDE_RESET_VECTOR=y diff --git a/boards/riscv/hifive1/Kconfig.board b/boards/riscv/hifive1/Kconfig.board index b5b326494411715..d2f40472f244d9a 100644 --- a/boards/riscv/hifive1/Kconfig.board +++ b/boards/riscv/hifive1/Kconfig.board @@ -2,4 +2,4 @@ config BOARD_HIFIVE1 bool "HiFive1 target" - depends on SOC_RISCV_SIFIVE_FREEDOM + depends on SOC_SIFIVE_FREEDOM_E340 diff --git a/boards/riscv/hifive1/hifive1_defconfig b/boards/riscv/hifive1/hifive1_defconfig index d37ded2bb25a1c8..8e4e8e21c1a2439 100644 --- a/boards/riscv/hifive1/hifive1_defconfig +++ b/boards/riscv/hifive1/hifive1_defconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_SIFIVE_FREEDOM=y -CONFIG_SOC_RISCV_SIFIVE_FREEDOM=y +CONFIG_SOC_SERIES_SIFIVE_FREEDOM_E300=y +CONFIG_SOC_SIFIVE_FREEDOM_E340=y CONFIG_BOARD_HIFIVE1=y CONFIG_CONSOLE=y CONFIG_SERIAL=y diff --git a/boards/riscv/hifive1_revb/Kconfig.board b/boards/riscv/hifive1_revb/Kconfig.board index d4c5b99ce72690c..b0bf1edd156bb1e 100644 --- a/boards/riscv/hifive1_revb/Kconfig.board +++ b/boards/riscv/hifive1_revb/Kconfig.board @@ -3,4 +3,4 @@ config BOARD_HIFIVE1_REVB bool "HiFive1 Rev B target" - depends on SOC_RISCV_SIFIVE_FREEDOM + depends on SOC_SIFIVE_FREEDOM_E340 diff --git a/boards/riscv/hifive1_revb/hifive1_revb_defconfig b/boards/riscv/hifive1_revb/hifive1_revb_defconfig index 4f691bd94354a91..b2119eecae9b594 100644 --- a/boards/riscv/hifive1_revb/hifive1_revb_defconfig +++ b/boards/riscv/hifive1_revb/hifive1_revb_defconfig @@ -1,5 +1,5 @@ -CONFIG_SOC_SERIES_RISCV_SIFIVE_FREEDOM=y -CONFIG_SOC_RISCV_SIFIVE_FREEDOM=y +CONFIG_SOC_SERIES_SIFIVE_FREEDOM_E300=y +CONFIG_SOC_SIFIVE_FREEDOM_E340=y CONFIG_BOARD_HIFIVE1_REVB=y CONFIG_GPIO=y CONFIG_PINCTRL=y diff --git a/boards/riscv/hifive_unleashed/Kconfig.board b/boards/riscv/hifive_unleashed/Kconfig.board index 4766e0ea7929eb8..f6c623e992817ec 100644 --- a/boards/riscv/hifive_unleashed/Kconfig.board +++ b/boards/riscv/hifive_unleashed/Kconfig.board @@ -3,4 +3,4 @@ config BOARD_HIFIVE_UNLEASHED bool "HiFive Unleashed target" - depends on SOC_RISCV_SIFIVE_FU540 + depends on SOC_SIFIVE_FREEDOM_U540 diff --git a/boards/riscv/hifive_unleashed/hifive_unleashed_defconfig b/boards/riscv/hifive_unleashed/hifive_unleashed_defconfig index 15c9e60d5527c66..51d324d457d337d 100644 --- a/boards/riscv/hifive_unleashed/hifive_unleashed_defconfig +++ b/boards/riscv/hifive_unleashed/hifive_unleashed_defconfig @@ -1,5 +1,5 @@ -CONFIG_SOC_SERIES_RISCV_SIFIVE_FREEDOM=y -CONFIG_SOC_RISCV_SIFIVE_FU540=y +CONFIG_SOC_SERIES_SIFIVE_FREEDOM_U500=y +CONFIG_SOC_SIFIVE_FREEDOM_U540=y CONFIG_BOARD_HIFIVE_UNLEASHED=y CONFIG_CONSOLE=y CONFIG_GPIO=y diff --git a/boards/riscv/hifive_unmatched/Kconfig.board b/boards/riscv/hifive_unmatched/Kconfig.board index cf6ac1c839203d9..bb303cc3aac4beb 100644 --- a/boards/riscv/hifive_unmatched/Kconfig.board +++ b/boards/riscv/hifive_unmatched/Kconfig.board @@ -3,4 +3,4 @@ config BOARD_HIFIVE_UNMATCHED bool "HiFive Unmatched target" - depends on SOC_RISCV_SIFIVE_FU740 + depends on SOC_SIFIVE_FREEDOM_U740 diff --git a/boards/riscv/hifive_unmatched/hifive_unmatched.yaml b/boards/riscv/hifive_unmatched/hifive_unmatched.yaml index 8b62698b61bf593..39450132d44f1eb 100644 --- a/boards/riscv/hifive_unmatched/hifive_unmatched.yaml +++ b/boards/riscv/hifive_unmatched/hifive_unmatched.yaml @@ -5,6 +5,8 @@ arch: riscv64 toolchain: - zephyr ram: 3840 +simulation: renode +simulation_exec: renode testing: ignore_tags: - net diff --git a/boards/riscv/hifive_unmatched/hifive_unmatched_defconfig b/boards/riscv/hifive_unmatched/hifive_unmatched_defconfig index 654fdc1bf2a615f..be13ed10358664a 100644 --- a/boards/riscv/hifive_unmatched/hifive_unmatched_defconfig +++ b/boards/riscv/hifive_unmatched/hifive_unmatched_defconfig @@ -1,5 +1,5 @@ -CONFIG_SOC_SERIES_RISCV_SIFIVE_FREEDOM=y -CONFIG_SOC_RISCV_SIFIVE_FU740=y +CONFIG_SOC_SERIES_SIFIVE_FREEDOM_U700=y +CONFIG_SOC_SIFIVE_FREEDOM_U740=y CONFIG_BOARD_HIFIVE_UNMATCHED=y CONFIG_CONSOLE=y CONFIG_SERIAL=y diff --git a/boards/riscv/it82xx2_evb/it82xx2_evb_defconfig b/boards/riscv/it82xx2_evb/it82xx2_evb_defconfig index f082e4a7badab60..6866e3f633b9487 100644 --- a/boards/riscv/it82xx2_evb/it82xx2_evb_defconfig +++ b/boards/riscv/it82xx2_evb/it82xx2_evb_defconfig @@ -1,7 +1,7 @@ # Copyright (c) 2023 ITE Corporation. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV32_IT8XXX2=y +CONFIG_SOC_SERIES_ITE_IT8XXX2=y CONFIG_SOC_IT8XXX2=y CONFIG_SOC_IT82202_AX=y CONFIG_BOARD_IT82XX2_EVB=y diff --git a/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig b/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig index 21967527f8ea2f0..38a44d6f8f3d35c 100644 --- a/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig +++ b/boards/riscv/it8xxx2_evb/it8xxx2_evb_defconfig @@ -1,7 +1,7 @@ # Copyright (c) 2020 ITE Corporation. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV32_IT8XXX2=y +CONFIG_SOC_SERIES_ITE_IT8XXX2=y CONFIG_SOC_IT8XXX2=y CONFIG_BOARD_IT8XXX2_EVB=y CONFIG_BOOT_DELAY=1 diff --git a/boards/riscv/m2gl025_miv/Kconfig.board b/boards/riscv/m2gl025_miv/Kconfig.board index 51c2f9d8de311ad..9f81fad406f355d 100644 --- a/boards/riscv/m2gl025_miv/Kconfig.board +++ b/boards/riscv/m2gl025_miv/Kconfig.board @@ -2,4 +2,4 @@ config BOARD_M2GL025_MIV bool "Microchip M2GL025 IGLOO2 dev board with Mi-V CPU" - depends on SOC_RISCV32_MIV + depends on SOC_MIV diff --git a/boards/riscv/m2gl025_miv/m2gl025_miv_defconfig b/boards/riscv/m2gl025_miv/m2gl025_miv_defconfig index 8c944a10a749018..e33765680d54415 100644 --- a/boards/riscv/m2gl025_miv/m2gl025_miv_defconfig +++ b/boards/riscv/m2gl025_miv/m2gl025_miv_defconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV32_MIV=y -CONFIG_SOC_RISCV32_MIV=y +CONFIG_SOC_SERIES_MIV=y +CONFIG_SOC_MIV=y CONFIG_BOARD_M2GL025_MIV=y CONFIG_CONSOLE=y CONFIG_SERIAL=y diff --git a/boards/riscv/mpfs_icicle/Kconfig.board b/boards/riscv/mpfs_icicle/Kconfig.board index 297f4ce4bc75f54..e772b82d7f58cf1 100644 --- a/boards/riscv/mpfs_icicle/Kconfig.board +++ b/boards/riscv/mpfs_icicle/Kconfig.board @@ -3,7 +3,7 @@ config BOARD_MPFS_ICICLE bool "Microchip PolarFire SoC ICICLE kit" - depends on SOC_MPFS + depends on SOC_POLARFIRE select 64BIT select SCHED_IPI_SUPPORTED select CPU_HAS_FPU_DOUBLE_PRECISION diff --git a/boards/riscv/mpfs_icicle/mpfs_icicle_defconfig b/boards/riscv/mpfs_icicle/mpfs_icicle_defconfig index 5c41649cb3ea37b..00b44f7a6d5a6db 100644 --- a/boards/riscv/mpfs_icicle/mpfs_icicle_defconfig +++ b/boards/riscv/mpfs_icicle/mpfs_icicle_defconfig @@ -1,8 +1,8 @@ # Copyright (c) 2020-2021 Microchip Technology Inc # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV64_MIV=y -CONFIG_SOC_MPFS=y +CONFIG_SOC_SERIES_POLARFIRE=y +CONFIG_SOC_POLARFIRE=y CONFIG_MPFS_HAL=n CONFIG_BASE64=y CONFIG_INCLUDE_RESET_VECTOR=y diff --git a/boards/riscv/neorv32/Kconfig.board b/boards/riscv/neorv32/Kconfig.board index eee37f4a8c3998b..6d85ebb2e402a5a 100644 --- a/boards/riscv/neorv32/Kconfig.board +++ b/boards/riscv/neorv32/Kconfig.board @@ -3,4 +3,4 @@ config BOARD_NEORV32 bool "NEORV32 Processor (SoC)" - depends on SOC_SERIES_NEORV32 + depends on SOC_NEORV32 diff --git a/boards/riscv/neorv32/neorv32_defconfig b/boards/riscv/neorv32/neorv32_defconfig index 17e9b8038cec428..7dc8a74ffff1641 100644 --- a/boards/riscv/neorv32/neorv32_defconfig +++ b/boards/riscv/neorv32/neorv32_defconfig @@ -1,7 +1,7 @@ # Copyright (c) 2021 Henrik Brix Andersen # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_NEORV32=y +CONFIG_SOC_NEORV32=y CONFIG_SOC_NEORV32_ISA_C=y CONFIG_BOARD_NEORV32=y CONFIG_SERIAL=y diff --git a/boards/riscv/opentitan_earlgrey/Kconfig.board b/boards/riscv/opentitan_earlgrey/Kconfig.board index ec7f735b442b9db..544c02b1b2aeb5a 100644 --- a/boards/riscv/opentitan_earlgrey/Kconfig.board +++ b/boards/riscv/opentitan_earlgrey/Kconfig.board @@ -3,4 +3,4 @@ config BOARD_OPENTITAN_EARLGREY bool "OpenTitan Earl Grey Target" - depends on SOC_RISCV_OPENTITAN + depends on SOC_OPENTITAN diff --git a/boards/riscv/opentitan_earlgrey/opentitan_earlgrey_defconfig b/boards/riscv/opentitan_earlgrey/opentitan_earlgrey_defconfig index 79299c3892f95bb..886e439b88ac420 100644 --- a/boards/riscv/opentitan_earlgrey/opentitan_earlgrey_defconfig +++ b/boards/riscv/opentitan_earlgrey/opentitan_earlgrey_defconfig @@ -1,8 +1,7 @@ # Copyright (c) 2023 by Rivos Inc. # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_OPENTITAN=y -CONFIG_SOC_RISCV_OPENTITAN=y +CONFIG_SOC_OPENTITAN=y CONFIG_BOARD_OPENTITAN_EARLGREY=y CONFIG_XIP=y CONFIG_SERIAL=y diff --git a/boards/riscv/qemu_riscv32/Kconfig.board b/boards/riscv/qemu_riscv32/Kconfig.board index 989fa13b4531476..7c94b59455cce24 100644 --- a/boards/riscv/qemu_riscv32/Kconfig.board +++ b/boards/riscv/qemu_riscv32/Kconfig.board @@ -22,7 +22,7 @@ config BOARD_QEMU_RISCV32_SMP config BOARD_QEMU_RISCV32_XIP bool "QEMU RISCV32 XIP target" - depends on SOC_RISCV_SIFIVE_FREEDOM + depends on SOC_SIFIVE_FREEDOM_E340 select QEMU_TARGET select HAS_COVERAGE_SUPPORT select CPU_HAS_FPU diff --git a/boards/riscv/qemu_riscv32/qemu_riscv32_defconfig b/boards/riscv/qemu_riscv32/qemu_riscv32_defconfig index f50d82dcb76c247..946e679a6e81ab0 100644 --- a/boards/riscv/qemu_riscv32/qemu_riscv32_defconfig +++ b/boards/riscv/qemu_riscv32/qemu_riscv32_defconfig @@ -1,6 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_VIRT=y CONFIG_SOC_RISCV_VIRT=y CONFIG_BOARD_QEMU_RISCV32=y CONFIG_CONSOLE=y diff --git a/boards/riscv/qemu_riscv32/qemu_riscv32_smp_defconfig b/boards/riscv/qemu_riscv32/qemu_riscv32_smp_defconfig index eef7d03e356d5a6..90f87ef6b988b80 100644 --- a/boards/riscv/qemu_riscv32/qemu_riscv32_smp_defconfig +++ b/boards/riscv/qemu_riscv32/qemu_riscv32_smp_defconfig @@ -1,6 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_VIRT=y CONFIG_SOC_RISCV_VIRT=y CONFIG_BOARD_QEMU_RISCV32_SMP=y CONFIG_CONSOLE=y diff --git a/boards/riscv/qemu_riscv32/qemu_riscv32_xip_defconfig b/boards/riscv/qemu_riscv32/qemu_riscv32_xip_defconfig index 2cd0b2cbecbba4d..948fa909a08548d 100644 --- a/boards/riscv/qemu_riscv32/qemu_riscv32_xip_defconfig +++ b/boards/riscv/qemu_riscv32/qemu_riscv32_xip_defconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_SIFIVE_FREEDOM=y -CONFIG_SOC_RISCV_SIFIVE_FREEDOM=y +CONFIG_SOC_SERIES_SIFIVE_FREEDOM_E300=y +CONFIG_SOC_SIFIVE_FREEDOM_E340=y CONFIG_BOARD_QEMU_RISCV32_XIP=y CONFIG_CONSOLE=y CONFIG_SERIAL=y diff --git a/boards/riscv/qemu_riscv32e/qemu_riscv32e_defconfig b/boards/riscv/qemu_riscv32e/qemu_riscv32e_defconfig index ef4d6273cfbda01..1f1c46acb10c64e 100644 --- a/boards/riscv/qemu_riscv32e/qemu_riscv32e_defconfig +++ b/boards/riscv/qemu_riscv32e/qemu_riscv32e_defconfig @@ -1,6 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_VIRT=y CONFIG_SOC_RISCV_VIRT=y CONFIG_BOARD_QEMU_RISCV32E=y CONFIG_CONSOLE=y diff --git a/boards/riscv/qemu_riscv64/qemu_riscv64_defconfig b/boards/riscv/qemu_riscv64/qemu_riscv64_defconfig index 6f51da3c59249ae..6bfc46ac907af87 100644 --- a/boards/riscv/qemu_riscv64/qemu_riscv64_defconfig +++ b/boards/riscv/qemu_riscv64/qemu_riscv64_defconfig @@ -1,6 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_VIRT=y CONFIG_SOC_RISCV_VIRT=y CONFIG_BOARD_QEMU_RISCV64=y CONFIG_PRIVILEGED_STACK_SIZE=2048 diff --git a/boards/riscv/qemu_riscv64/qemu_riscv64_smp_defconfig b/boards/riscv/qemu_riscv64/qemu_riscv64_smp_defconfig index 78b5b74de9ab494..265d84a1ded8310 100644 --- a/boards/riscv/qemu_riscv64/qemu_riscv64_smp_defconfig +++ b/boards/riscv/qemu_riscv64/qemu_riscv64_smp_defconfig @@ -1,6 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_VIRT=y CONFIG_SOC_RISCV_VIRT=y CONFIG_BOARD_QEMU_RISCV64_SMP=y CONFIG_PRIVILEGED_STACK_SIZE=2048 diff --git a/boards/riscv/riscv32_virtual/Kconfig.board b/boards/riscv/riscv32_virtual/Kconfig.board new file mode 100644 index 000000000000000..c8722acb384bb0c --- /dev/null +++ b/boards/riscv/riscv32_virtual/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RISCV32_VIRTUAL + bool "riscv32_virtual" + depends on SOC_RISCV32_VIRTUAL_RENODE diff --git a/boards/riscv/riscv32_virtual/Kconfig.defconfig b/boards/riscv/riscv32_virtual/Kconfig.defconfig new file mode 100644 index 000000000000000..840b10fd59443d1 --- /dev/null +++ b/boards/riscv/riscv32_virtual/Kconfig.defconfig @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "riscv32_virtual" + depends on BOARD_RISCV32_VIRTUAL diff --git a/boards/riscv/riscv32_virtual/board.cmake b/boards/riscv/riscv32_virtual/board.cmake new file mode 100644 index 000000000000000..cc177a69ce9ee95 --- /dev/null +++ b/boards/riscv/riscv32_virtual/board.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +set(SUPPORTED_EMU_PLATFORMS renode) +set(RENODE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/support/riscv32_virtual.resc) +set(RENODE_UART sysbus.uart0) diff --git a/boards/riscv/riscv32_virtual/doc/index.rst b/boards/riscv/riscv32_virtual/doc/index.rst new file mode 100644 index 000000000000000..a53384f533197f1 --- /dev/null +++ b/boards/riscv/riscv32_virtual/doc/index.rst @@ -0,0 +1,56 @@ +.. _riscv32-virtual: + +RISCV32 Virtual +############### + +Overview +******** + +The RISCV32 Virtual board is a virtual platform made with Renode as an alternative to QEMU. +Contrary to QEMU, the peripherals of this platform can be easily configured by editing the +``riscv32_virtual.repl`` script and the devicetree files accordingly, this allows certain hardware +configurations that only exist in proprietary boards/SoCs to be tested in upstream CI. + +Programming and debugging +************************* + +Building +======== + +Applications for the ``riscv32_virtual`` board configuration can be built as usual +(see :ref:`build_an_application`): + +.. zephyr-app-commands:: + :board: riscv32_virtual + :goals: build + +Flashing +======== + +While this board is emulated and you can't "flash" it, you can use this +configuration to run basic Zephyr applications and kernel tests in the Renode +emulated environment. For example, with the :zephyr:code-sample:`synchronization` sample: + +.. zephyr-app-commands:: + :zephyr-app: samples/synchronization + :host-os: unix + :board: riscv32_virtual + :goals: run + +This will build an image with the synchronization sample app, boot it using +Renode, and display the following console output: + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.5.0-1511-g56f73bde0fb0 *** + thread_a: Hello World from cpu 0 on riscv32_virtual! + thread_b: Hello World from cpu 0 on riscv32_virtual! + thread_a: Hello World from cpu 0 on riscv32_virtual! + thread_b: Hello World from cpu 0 on riscv32_virtual! + +Exit Renode by pressing :kbd:`CTRL+C`. + +Debugging +========= + +Refer to the detailed overview about :ref:`application_debugging`. diff --git a/boards/riscv/riscv32_virtual/riscv32_virtual.dts b/boards/riscv/riscv32_virtual/riscv32_virtual.dts new file mode 100644 index 000000000000000..326b97575180d48 --- /dev/null +++ b/boards/riscv/riscv32_virtual/riscv32_virtual.dts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "Renode RISCV32 Virtual target"; + compatible = "renode,riscv32-virtual"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + zephyr,sram = &sram0; + }; +}; + +&uart0 { + status = "okay"; +}; diff --git a/boards/riscv/riscv32_virtual/riscv32_virtual.yaml b/boards/riscv/riscv32_virtual/riscv32_virtual.yaml new file mode 100644 index 000000000000000..11cefb035df8e40 --- /dev/null +++ b/boards/riscv/riscv32_virtual/riscv32_virtual.yaml @@ -0,0 +1,16 @@ +identifier: riscv32_virtual +name: Renode RISC-V 32-bit Virtual Board +type: mcu +arch: riscv32 +toolchain: + - zephyr +ram: 4096 +flash: 4096 +simulation: renode +simulation_exec: renode +testing: + ignore_tags: + - net + - bluetooth +supported: + - uart diff --git a/boards/riscv/riscv32_virtual/riscv32_virtual_defconfig b/boards/riscv/riscv32_virtual/riscv32_virtual_defconfig new file mode 100644 index 000000000000000..4dcad0a7ea10404 --- /dev/null +++ b/boards/riscv/riscv32_virtual/riscv32_virtual_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_RISCV32_VIRTUAL_RENODE=y +CONFIG_BOARD_RISCV32_VIRTUAL=y +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=n +CONFIG_XIP=y + +# Workaround for incorrect SYS_CLOCK_HW_CYCLES_PER_SEC +CONFIG_SYS_CLOCK_TICKS_PER_SEC=100 diff --git a/boards/riscv/riscv32_virtual/support/riscv32_virtual.repl b/boards/riscv/riscv32_virtual/support/riscv32_virtual.repl new file mode 100644 index 000000000000000..e0df808631b6ca2 --- /dev/null +++ b/boards/riscv/riscv32_virtual/support/riscv32_virtual.repl @@ -0,0 +1,33 @@ +// Copyright (c) 2023 Meta +// SPDX-License-Identifier: Apache-2.0 + +flash: Memory.MappedMemory @ sysbus 0x80000000 + size: 0x400000 + +ddr: Memory.MappedMemory @ sysbus 0x80400000 + size: 0x400000 + +uart0: UART.NS16550 @ sysbus 0x10000000 + IRQ -> plic0@10 + +uart1: UART.NS16550 @ sysbus 0x10000100 + IRQ -> plic1@10 + +cpu: CPU.RiscV32 @ sysbus + cpuType: "rv32imac_zicsr_zifencei" + privilegeArchitecture: PrivilegeArchitecture.Priv1_10 + timeProvider: clint + +plic0: IRQControllers.PlatformLevelInterruptController @ sysbus 0x0C000000 + 0 -> cpu@11 + numberOfSources: 1023 + numberOfContexts: 1 + +plic1: IRQControllers.PlatformLevelInterruptController @ sysbus 0x08000000 + 0 -> cpu@4 + numberOfSources: 1023 + numberOfContexts: 1 + +clint: IRQControllers.CoreLevelInterruptor @ sysbus 0x02000000 + [0,1] -> cpu@[3,7] + frequency: 4000000 diff --git a/boards/riscv/riscv32_virtual/support/riscv32_virtual.resc b/boards/riscv/riscv32_virtual/support/riscv32_virtual.resc new file mode 100644 index 000000000000000..87e327287b61a96 --- /dev/null +++ b/boards/riscv/riscv32_virtual/support/riscv32_virtual.resc @@ -0,0 +1,17 @@ +:name: RISCV32-Virtual +:description: This script is prepared to run Zephyr on a Renode RISCV32 board. + +$name?="RISCV32-Virtual" + +using sysbus +mach create $name +machine LoadPlatformDescription $ORIGIN/riscv32_virtual.repl + +showAnalyzer uart0 +cpu PerformanceInMips 4 + +macro reset +""" + sysbus LoadELF $bin +""" +runMacro $reset diff --git a/boards/riscv/sparkfun_red_v_things_plus/Kconfig.board b/boards/riscv/sparkfun_red_v_things_plus/Kconfig.board index 34f852dc0ecb82d..cc9e7b4f935d857 100644 --- a/boards/riscv/sparkfun_red_v_things_plus/Kconfig.board +++ b/boards/riscv/sparkfun_red_v_things_plus/Kconfig.board @@ -3,4 +3,4 @@ config BOARD_SPARKFUN_RED_V_THINGS_PLUS bool "SparkFun RED-V Things Plus board" - depends on SOC_RISCV_SIFIVE_FREEDOM + depends on SOC_SIFIVE_FREEDOM_E340 diff --git a/boards/riscv/sparkfun_red_v_things_plus/sparkfun_red_v_things_plus_defconfig b/boards/riscv/sparkfun_red_v_things_plus/sparkfun_red_v_things_plus_defconfig index de3d18bcfdedf41..8cf24ffbe09f6de 100644 --- a/boards/riscv/sparkfun_red_v_things_plus/sparkfun_red_v_things_plus_defconfig +++ b/boards/riscv/sparkfun_red_v_things_plus/sparkfun_red_v_things_plus_defconfig @@ -1,8 +1,8 @@ # Copyright (c) 2022 TOKITA Hiroshi # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_SIFIVE_FREEDOM=y -CONFIG_SOC_RISCV_SIFIVE_FREEDOM=y +CONFIG_SOC_SERIES_SIFIVE_FREEDOM_E300=y +CONFIG_SOC_SIFIVE_FREEDOM_E340=y CONFIG_BOARD_SPARKFUN_RED_V_THINGS_PLUS=y CONFIG_GPIO=y CONFIG_PINCTRL=y diff --git a/boards/riscv/stamp_c3/stamp_c3_defconfig b/boards/riscv/stamp_c3/stamp_c3_defconfig index 3b5efc64fa11f11..021a4e841623505 100644 --- a/boards/riscv/stamp_c3/stamp_c3_defconfig +++ b/boards/riscv/stamp_c3/stamp_c3_defconfig @@ -5,8 +5,6 @@ CONFIG_SOC_SERIES_ESP32C3=y CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=1000000 - CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y diff --git a/boards/riscv/titanium_ti60_f225/Kconfig.board b/boards/riscv/titanium_ti60_f225/Kconfig.board index d6ed41ffc79d101..bac70816b205cb6 100644 --- a/boards/riscv/titanium_ti60_f225/Kconfig.board +++ b/boards/riscv/titanium_ti60_f225/Kconfig.board @@ -3,4 +3,4 @@ config BOARD_TITANIUM_TI60_F225 bool "Board with Efinix Sapphire riscv SoC" - depends on SOC_SERIES_EFINIX_SAPPHIRE + depends on SOC_EFINIX_SAPPHIRE diff --git a/boards/riscv/titanium_ti60_f225/titanium_ti60_f225_defconfig b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225_defconfig index 096980b864ecd09..0608a8e89537414 100644 --- a/boards/riscv/titanium_ti60_f225/titanium_ti60_f225_defconfig +++ b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225_defconfig @@ -1,7 +1,7 @@ # Copyright (c) 2023 Efinix Inc. # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_EFINIX_SAPPHIRE=y +CONFIG_SOC_EFINIX_SAPPHIRE=y CONFIG_BOARD_TITANIUM_TI60_F225=y CONFIG_CONSOLE=y CONFIG_SERIAL=y diff --git a/boards/riscv/tlsr9518adk80d/Kconfig.board b/boards/riscv/tlsr9518adk80d/Kconfig.board index bd36cb0e481f303..971b34dc13b4026 100644 --- a/boards/riscv/tlsr9518adk80d/Kconfig.board +++ b/boards/riscv/tlsr9518adk80d/Kconfig.board @@ -3,4 +3,4 @@ config BOARD_TLSR9518ADK80D bool "Telink B91 Platform" - depends on SOC_RISCV_TELINK_B91 + depends on SOC_TELINK_TLSR9518 diff --git a/boards/riscv/tlsr9518adk80d/tlsr9518adk80d_defconfig b/boards/riscv/tlsr9518adk80d/tlsr9518adk80d_defconfig index fe5cfbe8c2eb3ca..c4cfdfea718e4e0 100644 --- a/boards/riscv/tlsr9518adk80d/tlsr9518adk80d_defconfig +++ b/boards/riscv/tlsr9518adk80d/tlsr9518adk80d_defconfig @@ -1,8 +1,8 @@ # Copyright (c) 2021 Telink Semiconductor # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_SERIES_RISCV_TELINK_B91=y -CONFIG_SOC_RISCV_TELINK_B91=y +CONFIG_SOC_SERIES_TELINK_TLSR951X=y +CONFIG_SOC_TELINK_TLSR9518=y CONFIG_BOARD_TLSR9518ADK80D=y CONFIG_GPIO=y CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 diff --git a/boards/shields/esp_8266/boards/numaker_pfm_m467.overlay b/boards/shields/esp_8266/boards/numaker_pfm_m467.overlay new file mode 100644 index 000000000000000..f28bf527c9a88e7 --- /dev/null +++ b/boards/shields/esp_8266/boards/numaker_pfm_m467.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart2_esp8266: uart2_esp8266 { + group0 { + pinmux = , + , + , + ; + }; + }; +}; + +&uart2 { + status = "okay"; + current-speed = <115200>; + hw-flow-control; + + pinctrl-0 = <&uart2_esp8266>; + pinctrl-names = "default"; + + esp8266: esp8266 { + compatible = "espressif,esp-at"; + reset-gpios = <&gpioc 4 GPIO_ACTIVE_LOW>; + status = "okay"; + }; +}; + +&gpioc { + status = "okay"; +}; diff --git a/boards/shields/lmp90100_evb/lmp90100_evb.overlay b/boards/shields/lmp90100_evb/lmp90100_evb.overlay index 600eefdb1270303..7271c9c7c3debb9 100644 --- a/boards/shields/lmp90100_evb/lmp90100_evb.overlay +++ b/boards/shields/lmp90100_evb/lmp90100_evb.overlay @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + &arduino_spi { status = "okay"; @@ -13,7 +16,7 @@ spi-max-frequency = <1000000>; /* Uncomment to use IRQ instead of polling: */ /* drdyb-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; */ - #io-channel-cells = <2>; + #io-channel-cells = <1>; lmp90100_gpio: gpio { compatible = "ti,lmp90xxx-gpio"; diff --git a/boards/shields/st_b_lcd40_dsi1_mb1166/doc/index.rst b/boards/shields/st_b_lcd40_dsi1_mb1166/doc/index.rst index 407f8c6efdaa035..815b65f57501d2c 100644 --- a/boards/shields/st_b_lcd40_dsi1_mb1166/doc/index.rst +++ b/boards/shields/st_b_lcd40_dsi1_mb1166/doc/index.rst @@ -9,6 +9,9 @@ Overview The B-LCD40-DSI1 shield provides a 4-inch WVGA TFT LCD with MIPI DSI interface and capacitive touch screen. +.. note:: + Currently only the older version MB1166-A03 is supported by Zephyr. + The newer version MB1166-A09 does not get initialized correctly (see :github:`60888`). .. figure:: image.jpg :alt: B-LCD40-DSI1 MB1166 Image diff --git a/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay b/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay index dbb23935f03718f..e6dff3c9c9f331e 100644 --- a/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay +++ b/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay @@ -5,15 +5,14 @@ */ &arduino_spi { - cs-gpios = <&arduino_header 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* A1 */ + cs-gpios = <&arduino_header 1 GPIO_ACTIVE_LOW>; /* A1 */ spbtle_rf_x_nucleo_idb05a1: spbtle-rf@0 { - compatible = "zephyr,bt-hci-spi", "st,hci-spi-v1"; + compatible = "st,hci-spi-v1"; reg = <0>; - reset-gpios = <&arduino_header 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* D7 */ + reset-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ irq-gpios = <&arduino_header 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* A0 */ - spi-max-frequency = <2000000>; - controller-data-delay-us = <0>; /* No need for extra delay for BlueNRG-MS */ + spi-max-frequency = ; spi-hold-cs; }; }; diff --git a/boards/xtensa/kincony_kc868_a32/Kconfig.board b/boards/xtensa/kincony_kc868_a32/Kconfig.board new file mode 100644 index 000000000000000..098f377092bcecb --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/Kconfig.board @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Bartosz Bilas +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_KINCONY_KC868_A32 + bool "KINCONY KC868-A32 Board" + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_WROOM_32UE_N4 +endchoice diff --git a/boards/xtensa/kincony_kc868_a32/Kconfig.defconfig b/boards/xtensa/kincony_kc868_a32/Kconfig.defconfig new file mode 100644 index 000000000000000..229aaaeb4e3120d --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/Kconfig.defconfig @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Bartosz Bilas +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "kincony_kc868_a32" + depends on BOARD_KINCONY_KC868_A32 + +config ENTROPY_GENERATOR + default y + +config HEAP_MEM_POOL_SIZE + default 98304 if WIFI + default 40960 if BT + default 4096 diff --git a/boards/xtensa/kincony_kc868_a32/Kconfig.sysbuild b/boards/xtensa/kincony_kc868_a32/Kconfig.sysbuild new file mode 100644 index 000000000000000..bcf253836da160f --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) Bartosz Bilas +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/kincony_kc868_a32/board.cmake b/boards/xtensa/kincony_kc868_a32/board.cmake new file mode 100644 index 000000000000000..bf24ed1715081d6 --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/board.cmake @@ -0,0 +1,11 @@ +# Copyright (c) Bartosz Bilas +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() + +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/xtensa/kincony_kc868_a32/doc/img/kincony_kc868_a32.jpg b/boards/xtensa/kincony_kc868_a32/doc/img/kincony_kc868_a32.jpg new file mode 100644 index 000000000000000..9fa5685bb4d42eb Binary files /dev/null and b/boards/xtensa/kincony_kc868_a32/doc/img/kincony_kc868_a32.jpg differ diff --git a/boards/xtensa/kincony_kc868_a32/doc/index.rst b/boards/xtensa/kincony_kc868_a32/doc/index.rst new file mode 100644 index 000000000000000..dfd4797701bdd6f --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/doc/index.rst @@ -0,0 +1,97 @@ +.. _kincony_kc868_a32: + +KINCONY KC868-A32 +################# + +Overview +******** + +Kincony KC868-A32 is a home automation relay module based on the +Espressif ESP-WROOM-32 module with all its inherent capabilities +(Wi-Fi, Bluetooth, etc.) + +The features include the following: + +- 32 digital optoisolated inputs “dry contact” +- 4 analog inputs 0-5 V +- 32 relays 220 V, 10 A (COM, NO, NC) +- RS485 interface +- I2C connector +- Connector GSM/HMI +- Ethernet LAN8270A +- USB Type-B connector for programming and filling firmware +- RESET and DOWNLOAD buttons +- Powered by 12V DC + +.. figure:: img/kincony_kc868_a32.jpg + :align: center + :alt: KINCONCY-KC868-A32 + + KINCONCY-KC868-A32 + +System requirements +=================== + +Prerequisites +------------- + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +------------------- + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: kincony_kc868_a32 + :goals: build + +The usual ``flash`` target will work with the ``kincony_kc868_a32`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: kincony_kc868_a32 + :goals: flash + +Open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! kincony_kc868_a32 + +Enabling Ethernet +***************** + +Enable Ethernet in KConfig: + +.. code-block:: cfg + + CONFIG_NETWORKING=y + CONFIG_NET_L2_ETHERNET=y + CONFIG_MDIO=y + +References +********** + +.. _KINCONY KC868-A32 User Guide: https://www.kincony.com/arduino-esp32-32-channel-relay-module-kc868-a32.html diff --git a/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32-pinctrl.dtsi b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32-pinctrl.dtsi new file mode 100644 index 000000000000000..e1ee7cb2432c6db --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32-pinctrl.dtsi @@ -0,0 +1,49 @@ +/* + * Copyright (c) Bartosz Bilas + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , + ; + bias-pull-up; + drive-open-drain; + output-high; + }; + }; + + i2c1_default: i2c1_default { + group1 { + pinmux = , + ; + bias-pull-up; + drive-open-drain; + output-high; + }; + }; + + mdio_default: mdio_default { + group1 { + pinmux = , + ; + }; + }; +}; diff --git a/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.dts b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.dts new file mode 100644 index 000000000000000..da250ef781a7bf8 --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.dts @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2023 Bartosz Bilas + * + * SPDX-License-Identifier: Apache-2.0 + */ +/dts-v1/; + +#include +#include "kincony_kc868_a32-pinctrl.dtsi" + +/ { + model = "Kincony KC868-A32"; + compatible = "espressif,esp32"; + + aliases { + uart-0 = &uart0; + watchdog0 = &wdt0; + }; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; +}; + +&cpu0 { + clock-frequency = ; + cpu-power-states = <&light_sleep &deep_sleep>; +}; + +&cpu1 { + clock-frequency = ; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = ; + sda-gpios = <&gpio0 15 GPIO_OPEN_DRAIN>; + scl-gpios = <&gpio0 13 GPIO_OPEN_DRAIN>; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + + i2c0_pcf8574@21 { + compatible = "nxp,pcf8574"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + }; + + i2c0_pcf8574@22 { + compatible = "nxp,pcf8574"; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + }; + + i2c0_pcf8574@24 { + compatible = "nxp,pcf8574"; + reg = <0x24>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + }; + + i2c0_pcf8574@25 { + compatible = "nxp,pcf8574"; + reg = <0x25>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + }; +}; + +&i2c1 { + status = "okay"; + clock-frequency = ; + sda-gpios = <&gpio0 4 GPIO_OPEN_DRAIN>; + scl-gpios = <&gpio0 5 GPIO_OPEN_DRAIN>; + pinctrl-0 = <&i2c1_default>; + pinctrl-names = "default"; + + i2c1_pcf8574@21 { + compatible = "nxp,pcf8574"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + }; + + i2c1_pcf8574@22 { + compatible = "nxp,pcf8574"; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + }; + + i2c1_pcf8574@24 { + compatible = "nxp,pcf8574"; + reg = <0x24>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + }; + + i2c1_pcf8574@25 { + compatible = "nxp,pcf8574"; + reg = <0x25>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + }; +}; + +&mdio { + pinctrl-0 = <&mdio_default>; + pinctrl-names = "default"; + status = "okay"; + + phy: ethernet-phy@0 { + compatible = "ethernet-phy"; + status = "okay"; + reg = <0>; + }; +}; + +ð { + status = "okay"; + phy-handle = <&phy>; + ref-clk-output-gpios = <&gpio0 17 0>; +}; + +&psram0 { + status = "disabled"; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&timer2 { + status = "okay"; +}; + +&timer3 { + status = "okay"; +}; + +&trng0 { + status = "okay"; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@1000 { + label = "mcuboot"; + reg = <0x00001000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.yaml b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.yaml new file mode 100644 index 000000000000000..72577b2572a2e16 --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32.yaml @@ -0,0 +1,19 @@ +identifier: kincony_kc868_a32 +name: KINCONY-KC868-A32 +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - gpio + - i2c + - watchdog + - uart + - nvs + - counter + - entropy +testing: + ignore_tags: + - net + - bluetooth +vendor: kincony diff --git a/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32_defconfig b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32_defconfig new file mode 100644 index 000000000000000..7bb4a23e7949b16 --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/kincony_kc868_a32_defconfig @@ -0,0 +1,14 @@ +# Copyright (c) Bartosz Bilas +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_KINCONY_KC868_A32=y +CONFIG_SOC_SERIES_ESP32=y + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y + +CONFIG_GPIO=y +CONFIG_I2C=y diff --git a/boards/xtensa/kincony_kc868_a32/support/openocd.cfg b/boards/xtensa/kincony_kc868_a32/support/openocd.cfg new file mode 100644 index 000000000000000..338e6e4e6eae9a2 --- /dev/null +++ b/boards/xtensa/kincony_kc868_a32/support/openocd.cfg @@ -0,0 +1,5 @@ +set ESP_RTOS none +set ESP32_ONLYCPU 1 + +source [find interface/ftdi/esp32_devkitj_v1.cfg] +source [find target/esp32.cfg] diff --git a/boards/xtensa/m5stack_core2/m5stack_core2.dts b/boards/xtensa/m5stack_core2/m5stack_core2.dts index 5aa8e88bf2cf37e..c17b540ca5de419 100644 --- a/boards/xtensa/m5stack_core2/m5stack_core2.dts +++ b/boards/xtensa/m5stack_core2/m5stack_core2.dts @@ -46,6 +46,7 @@ lvgl_pointer { compatible = "zephyr,lvgl-pointer-input"; input = <&ft5336_touch>; + swap-xy; }; }; diff --git a/cmake/modules/shields.cmake b/cmake/modules/shields.cmake index 77abc4d603bc623..ec172512b685c62 100644 --- a/cmake/modules/shields.cmake +++ b/cmake/modules/shields.cmake @@ -79,41 +79,53 @@ foreach(root ${BOARD_ROOT}) list(REMOVE_ITEM SHIELD-NOTFOUND ${s}) - # Add .overlay to the shield_dts_files output variable. - list(APPEND - shield_dts_files - ${SHIELD_DIR_${s}}/${s}.overlay - ) - - # Add the shield's directory to the SHIELD_DIRS output variable. - list(APPEND - SHIELD_DIRS - ${SHIELD_DIR_${s}} - ) + # Add .overlay to a temporary variable + set(shield_${s}_dts_file ${SHIELD_DIR_${s}}/${s}.overlay) # Search for shield/shield.conf file if(EXISTS ${SHIELD_DIR_${s}}/${s}.conf) - # Add .conf to the shield_conf_files output variable. - list(APPEND - shield_conf_files - ${SHIELD_DIR_${s}}/${s}.conf - ) + # Add .conf to a temporary variable + set(shield_${s}_conf_file ${SHIELD_DIR_${s}}/${s}.conf) endif() - - # Add board-specific .conf and .overlay files to their - # respective output variables. - zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards - DTS shield_dts_files - KCONF shield_conf_files - ) - zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards/${s} - DTS shield_dts_files - KCONF shield_conf_files - ) endforeach() endif() endforeach() +# Process shields in-order +if(DEFINED SHIELD) + foreach(s ${SHIELD_AS_LIST}) + # Add .overlay to the shield_dts_files output variable. + list(APPEND + shield_dts_files + ${shield_${s}_dts_file} + ) + + # Add the shield's directory to the SHIELD_DIRS output variable. + list(APPEND + SHIELD_DIRS + ${SHIELD_DIR_${s}} + ) + + if(DEFINED shield_${s}_conf_file) + list(APPEND + shield_conf_files + ${shield_${s}_conf_file} + ) + endif() + + # Add board-specific .conf and .overlay files to their + # respective output variables. + zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards + DTS shield_dts_files + KCONF shield_conf_files + ) + zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards/${s} + DTS shield_dts_files + KCONF shield_conf_files + ) + endforeach() +endif() + # Prepare shield usage command printing. # This command prints all shields in the system in the following cases: # - User specifies an invalid SHIELD diff --git a/doc/conf.py b/doc/conf.py index af4b11fd0bb025c..f8bfb06e1991275 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -38,7 +38,7 @@ # -- Project -------------------------------------------------------------- project = "Zephyr Project" -copyright = "2015-2023 Zephyr Project members and individual contributors" +copyright = "2015-2024 Zephyr Project members and individual contributors" author = "The Zephyr Project Contributors" # parse version from 'VERSION' file diff --git a/doc/connectivity/bluetooth/api/index.rst b/doc/connectivity/bluetooth/api/index.rst index 9152aa7ff10a00f..fa7e357f7d84e35 100644 --- a/doc/connectivity/bluetooth/api/index.rst +++ b/doc/connectivity/bluetooth/api/index.rst @@ -39,3 +39,4 @@ Bluetooth APIs shell/iso.rst shell/mcp.rst shell/tmap.rst + shell/pbp.rst diff --git a/doc/connectivity/bluetooth/api/shell/pbp.rst b/doc/connectivity/bluetooth/api/shell/pbp.rst new file mode 100644 index 000000000000000..ba3e0f459fd5e49 --- /dev/null +++ b/doc/connectivity/bluetooth/api/shell/pbp.rst @@ -0,0 +1,20 @@ +Bluetooth: Public Broadcast Profile Shell +######################################### + +This document describes how to run the Public Broadcast Profile functionality. +PBP does not have an associated service. Its purpose is to enable a faster, more +efficient discovery of Broadcast Sources that are transmitting audio with commonly used codec configurations. + +Using the PBP Shell +******************* + +When the Bluetooth stack has been initialized (:code:`bt init`), the Public Broadcast Profile is ready to run. +To set the Public Broadcast Announcement features call :code:`pbp set_features`. + +.. code-block:: console + + + pbp --help + pbp - Bluetooth PBP shell commands + Subcommands: + set_features :Set the Public Broadcast Announcement features diff --git a/doc/connectivity/networking/api/ppp.rst b/doc/connectivity/networking/api/ppp.rst index d0028a075aae394..74e2da248f7fdf4 100644 --- a/doc/connectivity/networking/api/ppp.rst +++ b/doc/connectivity/networking/api/ppp.rst @@ -21,9 +21,8 @@ In Zephyr, each individual PPP link is modelled as a network interface. This is similar to how Linux implements PPP. PPP support must be enabled at compile time by setting option -:kconfig:option:`CONFIG_NET_PPP` and :kconfig:option:`CONFIG_NET_L2_PPP`. -The PPP support in Zephyr 2.0 is still experimental and the implementation -supports only these protocols: +:kconfig:option:`CONFIG_NET_L2_PPP`. +The PPP implementation supports only these protocols: * LCP (Link Control Protocol, `RFC1661 `__) @@ -34,9 +33,8 @@ supports only these protocols: * IPV6CP (IPv6 Control Protocol, `RFC5072 `__) -See also the :zephyr_file:`samples/net/sockets/echo_server/overlay-ppp.conf` -file for configuration option examples. -For using PPP with GSM modem, see :ref:`gsm_modem` for additional information. +For using PPP with a cellular modem, see :zephyr:code-sample:`cellular-modem` sample +for additional information. Testing ******* diff --git a/doc/contribute/bin_blobs.rst b/doc/contribute/bin_blobs.rst index efc25b609e17a61..14c181e4058dc1f 100644 --- a/doc/contribute/bin_blobs.rst +++ b/doc/contribute/bin_blobs.rst @@ -1,7 +1,7 @@ .. _bin-blobs: Binary Blobs -************ +############ In the context of an operating system that supports multiple architectures and many different IC families, some functionality may be unavailable without the @@ -22,7 +22,7 @@ therefore free to create Zephyr-based downstream software which uses binary blobs if they cannot meet the requirements described in this page. Software license -================ +**************** Most binary blobs are distributed under proprietary licenses which vary significantly in nature and conditions. It is up to the vendor to specify the @@ -30,7 +30,7 @@ license as part of the blob submission process. Blob vendors may impose a click-through or other EULA-like workflow when users fetch and install blobs. Hosting -======= +******* Blobs must be hosted on the Internet and managed by third-party infrastructure. Two potential examples are Git repositories and web servers managed by @@ -40,7 +40,7 @@ The Zephyr Project does not host binary blobs in its Git repositories or anywhere else. Fetching blobs -============== +************** Blobs are fetched from official third-party sources by the :ref:`west blobs ` command. @@ -76,7 +76,7 @@ Any accompanying code, including interface header files for the blobs, must be present in the corresponding module repository. Tainting -======== +******** Inclusion of binary blobs will taint the Zephyr build. The definition of tainting originates in the `Linux kernel @@ -96,7 +96,7 @@ Tainting will be communicated to the user in the following manners: .. _bin-blobs-types: Allowed types -============= +************* The following binary blob types are acceptable in Zephyr: @@ -121,7 +121,7 @@ In case of disagreement, the TSC is the arbiter of whether a particular blob fits in one of the above types. Precompiled library-specific requirements -========================================= +***************************************** This section contains additional requirements specific to precompiled library blobs. @@ -132,14 +132,14 @@ distribution if it is discovered that the blob fails to meet these requirements later on. Interface header files ----------------------- +====================== The precompiled library must be accompanied by one or more header files, distributed under a non-copyleft OSI approved license, that define the interface to the library. Allowed dependencies --------------------- +==================== This section defines requirements related to external symbols that a library blob requires the build system to provide. @@ -155,7 +155,7 @@ blob requires the build system to provide. released under an OSI approved license and documented using Doxygen Toolchain requirements ----------------------- +====================== Precompiled library blobs must be in a data format which is compatible with and can be linked by a toolchain supported by the Zephyr Project. This is required @@ -164,7 +164,7 @@ compiler and/or linker flags, however. For example, a porting layer may require special flags, or a static archive may require use of specific linker flags. Limited scope -------------- +============= Allowing arbitrary library blobs carries a risk of degrading the degree to which the upstream Zephyr software distribution is open source. As an extreme @@ -188,7 +188,7 @@ At the discretion of the release team, the project may remove support for a hardware target if it cannot pass this test suite. Support and maintenance -======================= +*********************** The Zephyr Project is not expected to be responsible for the maintenance and support of contributed binary blobs. As a consequence, at the discretion of the @@ -226,7 +226,7 @@ regularly scheduled execution of the CI infrastructure. .. _blobs-process: Submission and review process -============================= +***************************** For references to binary blobs to be included in the project, they must be reviewed and accepted by the Technical Steering Committee (TSC). This process is diff --git a/doc/contribute/contributor_expectations.rst b/doc/contribute/contributor_expectations.rst index aeb90c33d68e67b..cba1627a1b9be30 100644 --- a/doc/contribute/contributor_expectations.rst +++ b/doc/contribute/contributor_expectations.rst @@ -3,9 +3,6 @@ Contributor Expectations ######################## -Overview -******** - The Zephyr project encourages :ref:`contributors ` to submit changes as smaller pull requests. Smaller pull requests (PRs) have the following benefits: @@ -30,7 +27,7 @@ benefits: Defining Smaller PRs -==================== +******************** - Smaller PRs should encompass one self-contained logical change. @@ -55,7 +52,7 @@ Defining Smaller PRs Multiple Commits on a Single PR -=============================== +******************************* Contributors are further encouraged to break up PRs into multiple commits. Keep in mind each commit in the PR must still build cleanly and pass all the CI @@ -72,7 +69,7 @@ the PR into multiple commits targeting these specific changes: #. Update the documentation Large Changes -============= +************* Large changes to the Zephyr project must submit an :ref:`RFC proposal ` describing the full scope of change and future work. The RFC proposal provides @@ -265,7 +262,7 @@ the steps below: .. _reviewer-expectations: Reviewer Expectations -##################### +********************* - Be respectful when commenting on PRs. Refer to the Zephyr `Code of Conduct`_ for more details. diff --git a/doc/contribute/external.rst b/doc/contribute/external.rst index e602c94df09803b..c154bc3a698a81f 100644 --- a/doc/contribute/external.rst +++ b/doc/contribute/external.rst @@ -1,7 +1,7 @@ .. _external-contributions: Contributing External Components -******************************** +################################ In some cases it is desirable to leverage existing, external source code in order to avoid re-implementing basic functionality or features that are readily @@ -21,7 +21,7 @@ code analysis, testing or simulation please refer to the :ref:`external-tooling` section at the end of the page. Software License -================ +**************** .. note:: @@ -49,7 +49,7 @@ for contributed code, we ensure that the Zephyr community can develop products with the Zephyr Project without concerns over patent or copyright issues. Merit -===== +***** Just like with any other regular contribution, one that contains external code needs to be evaluated for merit. However, in the particular case of code that @@ -68,14 +68,14 @@ into the project: Are there other open source project that implement the same functionality? Mode of integration -=================== +******************* There are two ways of integrating external source code into the Zephyr Project, and careful consideration must be taken to choose the appropriate one for each particular case. Integration in the main tree ----------------------------- +============================ The first way to integrate external source code into the project is to simply import the source code files into the main ``zephyr`` repository. This @@ -94,7 +94,7 @@ This mode of integration can be applicable to both small and large external codebases, but it is typically used more commonly with the former. Integration as a module ------------------------ +======================= The second way of integrating external source code into the project is to import the whole or parts of the third-party open source project into a separate @@ -104,7 +104,7 @@ thus it is not automatically subject to the requirements of the previous section. Integration in main manifest file (west.yaml) -+++++++++++++++++++++++++++++++++++++++++++++ +--------------------------------------------- Integrating external code into the main :file:`west.yml` manifest file is limited to code that is used by a Zephyr subsystem (libraries), by a platform, @@ -117,7 +117,7 @@ Integrated modules will not be removed from the tree without a detailed migration plan. Integration as optional modules -+++++++++++++++++++++++++++++++ +------------------------------- Standalone or loose integration of modules/projects without any incoming dependencies shall be made optional and shall be kept standalone. Optional @@ -137,7 +137,7 @@ repository) and all sample or test code shall be maintained as part of the modul over time. Integration as external modules -+++++++++++++++++++++++++++++++ +------------------------------- Similar to optional modules, but added to the Zephyr project as an entry in the documentation using a pre-defined template. This type of modules exists outside the @@ -145,7 +145,7 @@ Zephyr project manifest with documentation instructing users and developers how to integrate the functionality. Ongoing maintenance -=================== +******************* Regardless of the mode of integration, external source code that is integrated in Zephyr requires regular ongoing maintenance. The submitter of the proposal to @@ -157,7 +157,7 @@ process. .. _external-src-process: Submission and review process -============================= +***************************** Before external source code can be included in the project, it must be reviewed and accepted by the Technical Steering Committee (TSC) and, in some cases, by diff --git a/doc/develop/test/twister.rst b/doc/develop/test/twister.rst index 0866653a636ced9..beaf12848682c7c 100644 --- a/doc/develop/test/twister.rst +++ b/doc/develop/test/twister.rst @@ -419,7 +419,7 @@ harness: Twister to be able to evaluate if a test passes criteria. For example, a keyboard harness is set on tests that require keyboard interaction to reach verdict on whether a test has passed or failed, however, Twister lack this - harness implementation at the momemnt. + harness implementation at the moment. Supported harnesses: @@ -445,6 +445,14 @@ harness: - net - bluetooth + Harness ``bsim`` is implemented in limited way - it helps only to copy the + final executable (``zephyr.exe``) from build directory to BabbleSim's + ``bin`` directory (``${BSIM_OUT_PATH}/bin``). This action is useful to allow + BabbleSim's tests to directly run after. By default, the executable file + name is (with dots and slashes replaced by underscores): + ``bs___``. + This name can be overridden with the ``bsim_exe_name`` option in + ``harness_config`` section. platform_key: Often a test needs to only be built and run once to qualify as passing. @@ -553,6 +561,11 @@ harness_config: robot_test_path: (default empty) Specify a path to a file containing a Robot Framework test suite to be run. + bsim_exe_name: + If provided, the executable filename when copying to BabbleSim's bin + directory, will be ``bs__`` instead of the + default based on the test path and scenario name. + The following is an example yaml file with a few harness_config options. .. code-block:: yaml diff --git a/doc/develop/test/ztest.rst b/doc/develop/test/ztest.rst index f9255ecad2a7e59..124fd415c2306f8 100644 --- a/doc/develop/test/ztest.rst +++ b/doc/develop/test/ztest.rst @@ -197,15 +197,15 @@ function can be written as follows: /* Only suites that use a predicate checking for phase == PWR_PHASE_0 will run. */ state.phase = PWR_PHASE_0; - ztest_run_all(&state); + ztest_run_all(&state, false, 1, 1); /* Only suites that use a predicate checking for phase == PWR_PHASE_1 will run. */ state.phase = PWR_PHASE_1; - ztest_run_all(&state); + ztest_run_all(&state, false, 1, 1); /* Only suites that use a predicate checking for phase == PWR_PHASE_2 will run. */ state.phase = PWR_PHASE_2; - ztest_run_all(&state); + ztest_run_all(&state, false, 1, 1); /* Check that all the suites in this binary ran at least once. */ ztest_verify_all_test_suites_ran(); @@ -553,9 +553,6 @@ See :ref:`FFF Extensions `. Customizing Test Output *********************** -The way output is presented when running tests can be customized. -An example can be found in :zephyr_file:`tests/ztest/custom_output`. - Customization is enabled by setting :kconfig:option:`CONFIG_ZTEST_TC_UTIL_USER_OVERRIDE` to "y" and adding a file :file:`tc_util_user_override.h` with your overrides. diff --git a/doc/develop/west/zephyr-cmds.rst b/doc/develop/west/zephyr-cmds.rst index 056d22e48ebde2f..f6b2322e6a4922a 100644 --- a/doc/develop/west/zephyr-cmds.rst +++ b/doc/develop/west/zephyr-cmds.rst @@ -89,6 +89,8 @@ To use this command: This step ensures the build directory contains CMake metadata required for SPDX document generation. +#. Enable :file:`CONFIG_BUILD_OUTPUT_META` in your project. + #. Build your application using this pre-created build directory, like so: .. code-block:: bash diff --git a/doc/hardware/emulator/bus_emulators.rst b/doc/hardware/emulator/bus_emulators.rst new file mode 100644 index 000000000000000..3568b0abbdc0506 --- /dev/null +++ b/doc/hardware/emulator/bus_emulators.rst @@ -0,0 +1,168 @@ +.. _bus_emul: + +External Bus and Bus Connected Peripherals Emulators +#################################################### + +Overview +======== + +Zephyr supports a simple emulator framework to support testing of external peripheral drivers +without requiring real hardware. + +Emulators are used to emulate external hardware devices, to support testing of +various subsystems. For example, it is possible to write an emulator +for an I2C compass such that it appears on the I2C bus and can be used +just like a real hardware device. + +Emulators often implement special features for testing. For example a +compass may support returning bogus data if the I2C bus speed is too +high, or may return invalid measurements if calibration has not yet +been completed. This allows for testing that high-level code can +handle these situations correctly. Test coverage can therefore +approach 100% if all failure conditions are emulated. + +Concept +======= + +The diagram below shows application code / high-level tests at the top. +This is the ultimate application we want to run. + +.. figure:: img/arch.svg + :align: center + :alt: Emulator architecture showing tests, emulators and drivers + +Below that are peripheral drivers, such as the AT24 EEPROM driver. We can test +peripheral drivers using an emulation driver connected via a emulated I2C +controller/emulator which passes I2C traffic from the AT24 driver to the AT24 +simulator. + +Separately we can test the STM32 and NXP I2C drivers on real hardware using API +tests. These require some sort of device attached to the bus, but with this, we +can validate much of the driver functionality. + +Putting the two together, we can test the application and peripheral code +entirely on native_sim. Since we know that the I2C driver on the real hardware +works, we should expect the application and peripheral drivers to work on the +real hardware also. + +Using the above framework we can test an entire application (e.g. Embedded +Controller) on native_sim using emulators for all non-chip drivers. + +With this approach we can: + +* Write individual tests for each driver (green), covering all failure modes, + error conditions, etc. + +* Ensure 100% test coverage for drivers (green) + +* Write tests for combinations of drivers, such as GPIOs provided by an I2C GPIO + expander driver talking over an I2C bus, with the GPIOs controlling a charger. + All of this can work in the emulated environment or on real hardware. + +* Write a complex application that ties together all of these pieces and runs on + native_sim. We can develop on a host, use source-level debugging, etc. + +* Transfer the application to any board which provides the required features + (e.g. I2C, enough GPIOs), by adding Kconfig and devicetree fragments. + +Creating a Device Driver Emulator +================================= + +The emulator subsystem is modeled on the :ref:`device_model_api`. You create +an emulator instance using one of the :c:func:`EMUL_DT_DEFINE()` or +:c:func:`EMUL_DT_INST_DEFINE()` APIs. + +Emulators for peripheral devices reuse the same devicetree node as the real +device driver. This means that your emulator defines `DT_DRV_COMPAT` using the +same ``compat`` value from the real driver. + +.. code-block:: C + + /* From drivers/sensor/bm160/bm160.c */ + #define DT_DRV_COMPAT bosch_bmi160 + + /* From drivers/sensor/bmi160/emul_bmi160.c */ + #define DT_DRV_COMPAT bosch_bmi160 + +The ``EMUL_DT_DEFINE()`` function accepts two API types: + + #. ``bus_api`` - This points to the API for the upstream bus that the emulator + connects to. The ``bus_api`` parameter is required. The supported + emulated bus types include I2C, SPI, and eSPI. + #. ``_backend_api`` - This points to the device-class specific backend API for + the emulator. The ``_backend_api`` parameter is optional. + +The diagram below demonstrates the logical organization of the ``bus_api`` and +``_backend_api`` using the BC1.2 charging detector driver as the model +device-class. + +.. figure:: img/device_class_emulator.svg + :align: center + :alt: Device class example, demonstrating BC1.2 charging detectors. + +The real code is shown in green, while the emulator code is shown in yellow. + +The ``bus_api`` connects the BC1.2 emulators to the ``native_sim`` I2C +controller. The real BC1.2 drivers are unchanged and operate exactly as if there +was a physical I2C controller present in the system. The ``native_sim`` I2C +controller uses the ``bus_api`` to initiate register reads and writes to the +emulator. + +The ``_backend_api`` provides a mechanism for tests to manipulate the emulator +out of band. Each device class defines it's own API functions. The backend API +functions focus on high-level behavior and do not provide hooks for specific +emulators. + +In the case of the BC1.2 charging detector the backend API provides functions +to simulate connecting and disconnecting a charger to the emulated BC1.2 device. +Each emulator is responsible for updating the correct vendor specific registers +and potentially signalling an interrupt. + +Example test flow: + + #. Test registers BC1.2 detection callback using the Zephyr BC1.2 driver API. + #. Test connects a charger using the BC1.2 emulator backend. + #. Test verifies B1.2 detection callback invoked with correct charger type. + #. Test disconnects a charger using the BC1.2 emulator backend. + +With this architecture, the same test can be used will all supported drivers in +the same driver class. + +Available Emulators +=================== + +Zephyr includes the following emulators: + +* I2C emulator driver, allowing drivers to be connected to an emulator so that + tests can be performed without access to the real hardware + +* SPI emulator driver, which does the same for SPI + +* eSPI emulator driver, which does the same for eSPI. The emulator is being + developed to support more functionalities. + +Samples +======= + +Here are some examples present in Zephyr: + +#. Bosch BMI160 sensor driver connected via both I2C and SPI to an emulator: + + .. zephyr-app-commands:: + :app: tests/drivers/sensor/accel/ + :board: native_sim + :goals: build + +#. The same test can be built with a second EEPROM which is an Atmel AT24 EEPROM driver + connected via I2C an emulator: + + .. zephyr-app-commands:: + :app: tests/drivers/eeprom/api + :board: native_sim + :goals: build + :gen-args: -DDTC_OVERLAY_FILE=at2x_emul.overlay -DOVERLAY_CONFIG=at2x_emul.conf + +API Reference +************* + +.. doxygengroup:: io_emulators diff --git a/doc/hardware/emulator/img/app.png b/doc/hardware/emulator/img/app.png deleted file mode 100644 index 25173530ca205e7..000000000000000 Binary files a/doc/hardware/emulator/img/app.png and /dev/null differ diff --git a/doc/hardware/emulator/img/arch.png b/doc/hardware/emulator/img/arch.png deleted file mode 100644 index eac62bf9da65553..000000000000000 Binary files a/doc/hardware/emulator/img/arch.png and /dev/null differ diff --git a/doc/hardware/emulator/img/arch.svg b/doc/hardware/emulator/img/arch.svg new file mode 100644 index 000000000000000..6aa5e703a7006b9 --- /dev/null +++ b/doc/hardware/emulator/img/arch.svg @@ -0,0 +1,4 @@ + + + +
Application
code / tests
Application...
Peripheral drivers
Peripheral drivers
Bus controller emulator
Bus controller em...
Peripheral
emulator
Peripheral...
API tests
API tests
STM32 drivers
STM32 drivers
NXP drivers
NXP drivers
STM32
HW
STM32...
NXP
HW
NXP...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/doc/hardware/emulator/img/device_class_emulator.png b/doc/hardware/emulator/img/device_class_emulator.png deleted file mode 100644 index ad64956fe6859de..000000000000000 Binary files a/doc/hardware/emulator/img/device_class_emulator.png and /dev/null differ diff --git a/doc/hardware/emulator/img/device_class_emulator.svg b/doc/hardware/emulator/img/device_class_emulator.svg new file mode 100644 index 000000000000000..a8615ff02a848dd --- /dev/null +++ b/doc/hardware/emulator/img/device_class_emulator.svg @@ -0,0 +1,4 @@ + + + +
Tests
Tests
BC1.2 Driver API
BC1.2 Driver API
Diodes
BC1.2 Driver
Diodes...
Mediatek BC1.2 Driver
Mediatek BC1....
I2C controller emulator
I2C controlle...
Diodes BC1.2 Emulator
Diodes BC1.2...
Mediatek BC1.2 Emulator
Mediatek BC1....
bus_api
bus_api
BC1.2 Backend API
BC1.2 Backend API
_backend API
_backend API
Text is not SVG - cannot display
\ No newline at end of file diff --git a/doc/hardware/emulator/index.rst b/doc/hardware/emulator/index.rst index 4373480a3e01531..0369876783ad0ff 100644 --- a/doc/hardware/emulator/index.rst +++ b/doc/hardware/emulator/index.rst @@ -1,189 +1,95 @@ .. _emulators: -Peripheral and Hardware Emulators -################################# +Zephyr's device emulators/simulators +#################################### Overview ======== -Zephyr supports a simple emulator framework to support testing of drivers -without requiring real hardware. +Zephyr includes in its codebase a set of device emulators/simulators. +With this we refer to SW components which are built together with the embedded SW +and present themselves as devices of a given class to the rest of the system. -Emulators are used to emulate hardware devices, to support testing of -various subsystems. For example, it is possible to write an emulator -for an I2C compass such that it appears on the I2C bus and can be used -just like a real hardware device. +These device emulators/simulators can be built for any target which has sufficient RAM and flash, +even if some may have extra functionality which is only available in some targets. -Emulators often implement special features for testing. For example a -compass may support returning bogus data if the I2C bus speed is too -high, or may return invalid measurements if calibration has not yet -been completed. This allows for testing that high-level code can -handle these situations correctly. Test coverage can therefore -approach 100% if all failure conditions are emulated. +.. note:: -Concept -======= + | Zephyr also includes and uses many other types of simulators/emulators, including CPU and + platform simulators, radio simulators, and several build targets which allow running the + embedded code in the development host. + | Some of Zephyr communication controllers/drivers include also either loopback modes or loopback + devices. + | This page does not cover any of these. -The diagram below shows application code / high-level tests at the top. -This is the ultimate application we want to run. +.. note:: + Drivers which are specific to some platform, like for example the + :ref:`native_sim specific drivers ` which + emulate a peripheral class by connecting to host APIs are not covered by this page. -.. figure:: img/arch.png - :align: center - :alt: Emulator architecture showing tests, emulators and drivers - -Below that are peripheral drivers, such as the AT24 EEPROM driver. We can test -peripheral drivers using an emulation driver connected via a native_sim I2C -controller/emulator which passes I2C traffic from the AT24 driver to the AT24 -simulator. - -Separately we can test the STM32 and NXP I2C drivers on real hardware using API -tests. These require some sort of device attached to the bus, but with this, we -can validate much of the driver functionality. - -Putting the two together, we can test the application and peripheral code -entirely on native_sim. Since we know that the I2C driver on the real hardware -works, we should expect the application and peripheral drivers to work on the -real hardware also. - -Using the above framework we can test an entire application (e.g. Embedded -Controller) on native_sim using emulators for all non-chip drivers: - -.. figure:: img/app.png - :align: center - :alt: Example system, using emulators to implement a PC EC - -The 'real' code is shown in green. The Zephyr emulation-framework code is shown -in yellow. The blue boxes are the extra code we have to write to emulate the -peripherals. - -With this approach we can: - -* Write individual tests for each driver (green), covering all failure modes, - error conditions, etc. - -* Ensure 100% test coverage for drivers (green) - -* Write tests for combinations of drivers, such as GPIOs provided by an I2C GPIO - expander driver talking over an I2C bus, with the GPIOs controlling a charger. - All of this can work in the emulated environment or on real hardware. - -* Write a complex application that ties together all of these pieces and runs on - native_sim. We can develop on a host, use source-level debugging, etc. - -* Transfer the application to any board which provides the required features - (e.g. I2C, enough GPIOs), by adding Kconfig and devicetree fragments. - -Creating a Device Driver Emulator -================================= - -The emulator subsystem is modeled on the :ref:`device_model_api`. You create -an emulator instance using one of the :c:func:`EMUL_DT_DEFINE()` or -:c:func:`EMUL_DT_INST_DEFINE()` APIs. - -Emulators for peripheral devices reuse the same devicetree node as the real -device driver. This means that your emulator defines `DT_DRV_COMPAT` using the -same ``compat`` value from the real driver. - -.. code-block:: C - - /* From drivers/sensor/bm160/bm160.c */ - #define DT_DRV_COMPAT bosch_bmi160 - - /* From subsys/emul/emul_bmi160.c */ - #define DT_DRV_COMPAT bosch_bmi160 - -The ``EMUL_DT_DEFINE()`` function accepts two API types: - - #. ``bus_api`` - This points to the API for the upstream bus that the emulator - connects to. The ``bus_api`` parameter is required. The supported - emulated bus types include I2C, SPI, and eSPI. - #. ``_backend_api`` - This points to the device-class specific backend API for - the emulator. The ``_backend_api`` parameter is optional. - -The diagram below demonstrates the logical organization of the ``bus_api`` and -``_backend_api`` using the BC1.2 charging detector driver as the model -device-class. - -.. figure:: img/device_class_emulator.png - :align: center - :alt: Device class example, demonstrating BC1.2 charging detectors. - -The real code is shown in green, while the emulator code is shown in yellow. - -The ``bus_api`` connects the BC1.2 emulators to the ``native_sim`` I2C -controller. The real BC1.2 drivers are unchanged and operate exactly as if there -was a physical I2C controller present in the system. The ``native_sim`` I2C -controller uses the ``bus_api`` to initiate register reads and writes to the -emulator. - -The ``_backend_api`` provides a mechanism for tests to manipulate the emulator -out of band. Each device class defines it's own API functions. The backend API -functions focus on high-level behavior and do not provide hooks for specific -emulators. - -In the case of the BC1.2 charging detector the backend API provides functions -to simulate connecting and disconnecting a charger to the emulated BC1.2 device. -Each emulator is responsible for updating the correct vendor specific registers -and potentially signalling an interrupt. - -Example test flow: - - #. Test registers BC1.2 detection callback using the Zephyr BC1.2 driver API. - #. Test connects a charger using the BC1.2 emulator backend. - #. Test verifies B1.2 detection callback invoked with correct charger type. - #. Test disconnects a charger using the BC1.2 emulator backend. - -With this architecture, the same test can be used will all supported drivers in -the same driver class. Available Emulators =================== -Zephyr includes the following emulators: - -* EEPROM, which uses a file as the EEPROM contents - -* I2C emulator driver, allowing drivers to be connected to an emulator so that - tests can be performed without access to the real hardware - -* SPI emulator driver, which does the same for SPI - -* eSPI emulator driver, which does the same for eSPI. The emulator is being - developed to support more functionalities. - -* CAN loopback driver - -A GPIO emulator is planned but is not yet complete. - -Samples -======= - -Here are some examples present in Zephyr: - -#. Bosch BMI160 sensor driver connected via both I2C and SPI to an emulator: - - .. zephyr-app-commands:: - :app: tests/drivers/sensor/accel/ - :board: native_sim - :goals: build - -#. Simple test of the EEPROM emulator: - - .. zephyr-app-commands:: - :app: tests/drivers/eeprom/api - :board: native_sim - :goals: build - -#. The same test can be built with a second EEPROM which is an Atmel AT24 EEPROM driver - connected via I2C an emulator: - - .. zephyr-app-commands:: - :app: tests/drivers/eeprom/api - :board: native_sim - :goals: build - :gen-args: -DDTC_OVERLAY_FILE=at2x_emul.overlay -DOVERLAY_CONFIG=at2x_emul.conf - -API Reference -************* - -.. doxygengroup:: io_emulators +**ADC emulator** + * A fake driver which pretends to be actual ADC, and can be used for testing higher-level API + for ADC devices. + * Main Kconfig option: :kconfig:option:`CONFIG_ADC_EMUL` + * DT binding: :dtcompatible:`zephyr,adc-emul` + +**DMA emulator** + * Emulated DMA controller + * Main Kconfig option: :kconfig:option:`CONFIG_DMA_EMUL` + * DT binding: :dtcompatible:`zephyr,dma-emul` + +**EEPROM emulator** + * Emulate an EEPROM on a flash partition + * Main Kconfig option: :kconfig:option:`CONFIG_EEPROM_EMULATOR` + * DT binding: :dtcompatible:`zephyr,emu-eeprom` + +.. _emul_eeprom_simu_brief: + +**EEPROM simulator** + * Emulate an EEPROM on RAM + * Main Kconfig option: :kconfig:option:`CONFIG_EEPROM_SIMULATOR` + * DT binding: :dtcompatible:`zephyr,sim-eeprom` + * Note: For :ref:`native targets ` it is also possible to keep the content + as a file on the host filesystem. + +**External bus and bus connected peripheral emulators** + * :ref:`Documentation ` + * Allow emulating external buses like I2C or SPI and peripherals connected to them. + +.. _emul_flash_simu_brief: + +**Flash simulator** + * Emulate a flash on RAM + * Main Kconfig option: :kconfig:option:`CONFIG_FLASH_SIMULATOR` + * DT binding: :dtcompatible:`zephyr,sim-flash` + * Note: For native targets it is also possible to keep the content as a file on the host + filesystem. Check :ref:`the native_sim flash simulator section `. + +**GPIO emulator** + * Emulated GPIO controllers which can be driven from SW + * Main Kconfig option: :kconfig:option:`CONFIG_GPIO_EMUL` + * DT binding: :dtcompatible:`zephyr,gpio-emul` + +**I2C emulator** + * Emulated I2C bus. See :ref:`bus emulators `. + * Main Kconfig option: :kconfig:option:`CONFIG_I2C_EMUL` + * DT binding: :dtcompatible:`zephyr,i2c-emul-controller` + +**RTC emulator** + * Emulated RTC peripheral. See :ref:`RTC emulated device section ` + * Main Kconfig option: :kconfig:option:`CONFIG_RTC_EMUL` + * DT binding: :dtcompatible:`zephyr,rtc-emul` + +**SPI emulator** + * Emulated SPI bus. See :ref:`bus emulators `. + * Main Kconfig option: :kconfig:option:`CONFIG_SPI_EMUL` + * DT binding: :dtcompatible:`zephyr,spi-emul-controller` + +**UART emulator** + * Emulated UART bus. See :ref:`bus emulators `. + * Main Kconfig option: :kconfig:option:`CONFIG_UART_EMUL` + * DT binding: :dtcompatible:`zephyr,uart-emul` diff --git a/doc/hardware/index.rst b/doc/hardware/index.rst index c9ba1c92f8ae3ea..72e9cc5fd0561ad 100644 --- a/doc/hardware/index.rst +++ b/doc/hardware/index.rst @@ -10,6 +10,7 @@ Hardware Support barriers/index.rst cache/index.rst emulator/index.rst + emulator/bus_emulators.rst peripherals/index.rst pinctrl/index.rst porting/index diff --git a/doc/hardware/peripherals/can/index.rst b/doc/hardware/peripherals/can/index.rst index 6e96fb15cb224b9..c605bdd03010fcc 100644 --- a/doc/hardware/peripherals/can/index.rst +++ b/doc/hardware/peripherals/can/index.rst @@ -8,3 +8,4 @@ Controller Area Network (CAN) controller.rst transceiver.rst + shell.rst diff --git a/doc/hardware/peripherals/can/shell.rst b/doc/hardware/peripherals/can/shell.rst new file mode 100644 index 000000000000000..cfd016843d0dc04 --- /dev/null +++ b/doc/hardware/peripherals/can/shell.rst @@ -0,0 +1,266 @@ +.. _can_shell: + +CAN Shell +######### + +.. contents:: + :local: + :depth: 1 + +Overview +******** + +The CAN shell provides a ``can`` command with a set of subcommands for the :ref:`shell ` +module. It allows for testing and exploring the :ref:`can_api` driver API through an interactive +interface without having to write a dedicated application. The CAN shell can also be enabled in +existing applications to aid in interactive debugging of CAN issues. + +The CAN shell provides access to most CAN controller features, including inspection, configuration, +sending and receiving of CAN frames, and bus recovery. + +In order to enable the CAN shell, the following :ref:`Kconfig ` options must be enabled: + +* :kconfig:option:`CONFIG_SHELL` +* :kconfig:option:`CONFIG_CAN` +* :kconfig:option:`CONFIG_CAN_SHELL` + +The following :ref:`Kconfig ` options enable additional subcommands and features of the +``can`` command: + +* :kconfig:option:`CONFIG_CAN_FD_MODE` enables CAN FD specific subcommands (e.g. for setting the + timing for the CAN FD data phase). +* :kconfig:option:`CONFIG_CAN_RX_TIMESTAMP` enables printing of timestamps for received CAN frames. +* :kconfig:option:`CONFIG_CAN_STATS` enables printing of various statistics for the CAN controller + in the ``can show`` subcommand. This depends on :kconfig:option:`CONFIG_STATS` being enabled as + well. +* :kconfig:option:`CONFIG_CAN_AUTO_BUS_OFF_RECOVERY` enables the ``can recover`` subcommand when + disabled. + +For example, building the :ref:`hello_world` sample for the :ref:`frdm_k64f` with the CAN shell and +CAN statistics enabled: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_k64f + :gen-args: -DCONFIG_SHELL=y -DCONFIG_CAN=y -DCONFIG_CAN_SHELL=y -DCONFIG_STATS=y -DCONFIG_CAN_STATS=y + :goals: build + +See the :ref:`shell ` documentation for general instructions on how to connect and +interact with the shell. The CAN shell comes with built-in help (unless +:kconfig:option:`CONFIG_SHELL_HELP` is disabled). The built-in help messages can be printed by +passing ``-h`` or ``--help`` to the ``can`` command or any of its subcommands. All subcommands also +support tab-completion of their arguments. + +.. tip:: + All of the CAN shell subcommands take the name of a CAN controller as their first argument, which + also supports tab-completion. A list of all devices available can be obtained using the ``device + list`` shell command when :kconfig:option:`CONFIG_DEVICE_SHELL` is enabled. The examples below + all use the device name ``can@0``. + +Inspection +********** + +The properties of a given CAN controller can be inspected using the ``can show`` subcommand as shown +below. The properties include the core CAN clock rate, the maximum supported bitrate, the number of +RX filters supported, capabilities, current state, error counters, timing limits, and more: + +.. code-block:: console + + uart:~$ can show can@0 + core clock: 144000000 Hz + max bitrate: 5000000 bps + max std filters: 15 + max ext filters: 15 + capabilities: normal loopback listen-only fd + state: stopped + rx errors: 0 + tx errors: 0 + timing: sjw 1..128, prop_seg 0..0, phase_seg1 2..256, phase_seg2 2..128, prescaler 1..512 + timing data: sjw 1..16, prop_seg 0..0, phase_seg1 1..32, phase_seg2 1..16, prescaler 1..32 + statistics: + bit errors: 0 + bit0 errors: 0 + bit1 errors: 0 + stuff errors: 0 + crc errors: 0 + form errors: 0 + ack errors: 0 + rx overruns: 0 + +.. note:: + The statistics are only printed if :kconfig:option:`CONFIG_CAN_STATS` is enabled. + +Configuration +************* + +The CAN shell allows for configuring the CAN controller mode and timing, along with starting and +stopping the processing of CAN frames. + +.. note:: + The CAN controller mode and timing can only be changed while the CAN controller is stopped, which + is the initial setting upon boot-up. The initial CAN controller mode is set to ``normal`` and the + initial timing is set according to the ``bus-speed``, ``sample-point``, ``bus-speed-data``, and + ``sample-point-data`` :ref:`devicetree` properties. + +Timing +====== + +The classic CAN bitrate/CAN FD arbitration phase bitrate can be configured using the ``can bitrate`` +subcommand as shown below. The bitrate is specified in bits per second. + +.. code-block:: console + + uart:~$ can bitrate can@0 125000 + setting bitrate to 125000 bps + +If :kconfig:option:`CONFIG_CAN_FD_MODE` is enabled, the data phase bitrate can be configured using +the ``can dbitrate`` subcommand as shown below. The bitrate is specified in bits per second. + +.. code-block:: console + + uart:~$ can dbitrate can@0 1000000 + setting data bitrate to 1000000 bps + +Both of these subcommands allow specifying an optional sample point in per mille and a +(Re)Synchronization Jump Width (SJW) in Time Quanta as positional arguments. Refer to the +interactive help of the subcommands for more details. + +It is also possible to configure the raw bit timing using the ``can timing`` and ``can dtiming`` +subcommands. Refer to the interactive help output for these subcommands for details on the required +arguments. + +Mode +==== + +The CAN shell allows for setting the mode of the CAN controller using the ``can mode`` +subcommand. An example for enabling loopback mode is shown below. + +.. code-block:: console + + uart:~$ can mode can@0 loopback + setting mode 0x00000001 + +The subcommand accepts multiple modes given on the same command line (e.g. ``can mode can@0 fd +loopback`` for setting CAN FD and loopback mode). Vendor-specific modes can be specified in +hexadecimal. + +Starting and Stopping +===================== + +After the timing and mode has been configured as needed, the CAN controller can be started using the +``can start`` subcommand as shown below. This will enable reception and transmission of CAN frames. + +.. code-block:: console + + uart:~$ can start can@0 + starting can@0 + +Prior to reconfiguring the timing or mode, the CAN controller needs to be stopped using the ``can +stop`` subcommand as shown below: + +.. code-block:: console + + uart:~$ can stop can@0 + stopping can@0 + +Receiving +********* + +In order to receive CAN frames, one or more CAN RX filters need to be configured. CAN RX filters are +added using the ``can filter add`` subcommand as shown below. The subcommand accepts a CAN ID in +hexadecimal format along with an optional CAN ID mask, also in hexadecimal format, for setting which +bits in the CAN ID are to be matched. Refer to the interactive help output for this subcommand for +further details on the supported arguments. + +.. code-block:: console + + uart:~$ can filter add can@0 010 + adding filter with standard (11-bit) CAN ID 0x010, CAN ID mask 0x7ff, data frames 1, RTR frames 0, CAN FD frames 0 + filter ID: 0 + +The filter ID (0 in the example above) returned is to be used when removing the CAN RX filter. + +Received CAN frames matching the added filter(s) are printed to the shell. A few examples are shown below: + +.. code-block:: console + + # Flags ID Size Data bytes + -- 010 [8] 01 02 03 04 05 06 07 08 + B- 010 [08] 01 02 03 04 05 06 07 08 + BP 010 [03] 01 aa bb + -- 00000010 [0] + -- 010 [1] 20 + -- 010 [8] remote transmission request + +The columns have the following meaning: + +* Flags + + * ``B``: The frame has the CAN FD Baud Rate Switch (BRS) flag set. + * ``P``: The frame has the CAN FD Error State Indicator (ESI) flag set. The transmitting node is + in error-passive state. + * ``-``: Unset flag. + +* ID + + * ``010``: The standard (11-bit) CAN ID of the frame in hexadecimal format, here 10h. + * ``00000010``: The extended (29-bit) CAN ID of the frame in hexadecimal format, here 10h. + +* Size + + * ``[8]``: The number of frame data bytes in decimal format, here a classic CAN frame with 8 data + bytes. + * ``[08]``: The number of frame data bytes in decimal format, here a CAN FD frame with 8 data + bytes. + +* Data bytes + + * ``01 02 03 04 05 06 07 08``: The frame data bytes in hexadecimal format, here the numbers from 1 + through 8. + * ``remote transmission request``: The frame is a Remote Transmission Request (RTR) frame and thus + carries no data bytes. + +.. tip:: + If :kconfig:option:`CONFIG_CAN_RX_TIMESTAMP` is enabled, each line will be prepended with a + timestamp from the free-running timestamp counter in the CAN controller. + +Configured CAN RX filters can be removed again using the ``can filter remove`` subcommand as shown +below. The filter ID is the ID returned by the ``can filter add`` subcommand (0 in the example +below). + +.. code-block:: console + + uart:~$ can filter remove can@0 0 + removing filter with ID 0 + +Sending +******* + +CAN frames can be queued for transmission using the ``can send`` subcommand as shown below. The +subcommand accepts a CAN ID in hexadecimal format and optionally a number of data bytes, also +specified in hexadecimal. Refer to the interactive help output for this subcommand for further +details on the supported arguments. + +.. code-block:: console + + uart:~$ can send can@0 010 1 2 3 4 5 6 7 8 + enqueuing CAN frame #2 with standard (11-bit) CAN ID 0x010, RTR 0, CAN FD 0, BRS 0, DLC 8 + CAN frame #2 successfully sent + +Bus Recovery +************ + +The ``can recover`` subcommand can be used for initiating recovery from a CAN bus-off event as shown +below: + +.. code-block:: console + + uart:~$ can recover can@0 + recovering, no timeout + +The subcommand accepts an optional bus recovery timeout in milliseconds. If no timeout is specified, +the command will wait indefinitely for the bus recovery to succeed. + +.. note:: + The ``recover`` subcommand is only available if + :kconfig:option:`CONFIG_CAN_AUTO_BUS_OFF_RECOVERY` is disabled. diff --git a/doc/hardware/peripherals/rtc.rst b/doc/hardware/peripherals/rtc.rst index d2552d078ee7851..ae69df0b4464eea 100644 --- a/doc/hardware/peripherals/rtc.rst +++ b/doc/hardware/peripherals/rtc.rst @@ -126,3 +126,24 @@ be printed to the console. .. note:: The tests take up to 30 seconds each if they are testing real hardware. + +.. _rtc_api_emul_dev: + +RTC emulated device +******************* + +The emulated RTC device fully implements the RTC API, and will behave like a real +RTC device, with the following limitations: + +* RTC time is not persistent across application initialization. +* RTC alarms are not persistent across application initialization. +* RTC time will drift over time. + +Every time an application is initialized, the RTC's time and alarms are reset. Reading +the time using :c:func:`rtc_get_time` will return ``-ENODATA``, until the time is +set using :c:func:`rtc_set_time`. The RTC will then behave as a real RTC, until the +application is reset. + +The emulated RTC device driver is built for the compatible +:dtcompatible:`zephyr,rtc-emul` and will be included if :kconfig:option:`CONFIG_RTC` +is selected. diff --git a/doc/kernel/services/other/atomic.rst b/doc/kernel/services/other/atomic.rst index 6d739209ae63f72..3e589a4cad39b7b 100644 --- a/doc/kernel/services/other/atomic.rst +++ b/doc/kernel/services/other/atomic.rst @@ -4,8 +4,8 @@ Atomic Services ############### An :dfn:`atomic variable` is one that can be read and modified -by threads and ISRs in an uninterruptible manner. It 32-bit on -32-bit machines and 64-bit on 64-bit machines. +by threads and ISRs in an uninterruptible manner. It is a 32-bit variable on +32-bit machines and a 64-bit variable on 64-bit machines. .. contents:: :local: diff --git a/doc/project/project_roles.rst b/doc/project/project_roles.rst index e6f7b6d9d56870f..a57a7b46def4b69 100644 --- a/doc/project/project_roles.rst +++ b/doc/project/project_roles.rst @@ -178,7 +178,7 @@ team to ensure that static analysis defects opened during a release cycle are properly addressed. The team has the following rights and responsibilities: -* Right to revert any change in a static analysis tool (e.g: Coverity) +* Right to revert any triage in a static analysis tool (e.g: Coverity) that does not follow the project expectations. * Responsibility to inform code owners about improper classifications. * Responsibility to alert TSC if any issues are not adequately addressed by the diff --git a/doc/releases/migration-guide-3.6.rst b/doc/releases/migration-guide-3.6.rst index 434bc9368c5e43f..22321e8e9b925a3 100644 --- a/doc/releases/migration-guide-3.6.rst +++ b/doc/releases/migration-guide-3.6.rst @@ -146,6 +146,19 @@ Device Drivers and Device Tree * The main Kconfig option was renamed from ``CONFIG_CAN_NATIVE_POSIX_LINUX`` to :kconfig:option:`CONFIG_CAN_NATIVE_LINUX`. +* The io-channel cells of the following devicetree bindings were reduced from 2 (``positive`` and + ``negative``) to the common ``input``, making it possible to use the various ADC DT macros with TI + LMP90xxx ADC devices: + + * :dtcompatible:`ti,lmp90077` + * :dtcompatible:`ti,lmp90078` + * :dtcompatible:`ti,lmp90079` + * :dtcompatible:`ti,lmp90080` + * :dtcompatible:`ti,lmp90097` + * :dtcompatible:`ti,lmp90098` + * :dtcompatible:`ti,lmp90099` + * :dtcompatible:`ti,lmp90100` + Power Management ================ diff --git a/doc/releases/release-notes-3.6.rst b/doc/releases/release-notes-3.6.rst index c86fb41d09a964f..d213ccba2591139 100644 --- a/doc/releases/release-notes-3.6.rst +++ b/doc/releases/release-notes-3.6.rst @@ -138,6 +138,14 @@ Build system and infrastructure * Added MCUboot image size reduction to sysbuild images which include MCUboot which prevents issues with building firmware images that are too large for MCUboot to swap. +* Deprecated :kconfig:option:`CONFIG_BOOTLOADER_SRAM_SIZE`, users of this should transition to + having RAM set up properly in their board devicetree files. + +* Fixed an issue whereby shields were processed in order of the root they resided in rather than + the order they were supplied to cmake in. + +* Fixed an issue whereby using some shields with sysbuild would cause a cmake Kconfig error. + Drivers and Sensors ******************* @@ -182,6 +190,8 @@ Drivers and Sensors * IEEE 802.15.4 + * Removed :kconfig:option:`CONFIG_IEEE802154_SELECTIVE_TXPOWER` Kconfig option. + * Interrupt Controller * Input diff --git a/doc/security/vulnerabilities.rst b/doc/security/vulnerabilities.rst index 2ee308c6450826d..a03b5202a028175 100644 --- a/doc/security/vulnerabilities.rst +++ b/doc/security/vulnerabilities.rst @@ -1596,3 +1596,19 @@ This has been fixed in main for v3.5.0 - `PR 63605 fix for main `_ + + +CVE-2023-5779 +------------- + +Under embargo until 2024-01-23 + +CVE-2023-6249 +------------- + +Under embargo until 2024-02-18 + +CVE-2023-6749 +------------- + +Under embargo until 2024-02-18 diff --git a/doc/services/input/diodes-cr.svg b/doc/services/input/diodes-cr.svg new file mode 100644 index 000000000000000..d374b8e0c412568 --- /dev/null +++ b/doc/services/input/diodes-cr.svg @@ -0,0 +1,6140 @@ + + + + SVG Image created as keyboard-matrix-testboard-diodes-cr.svg date 2023/12/18 09:58:32 + Image generated by Eeschema-SVG + + + + + + + + + + + + + + + + + + + + + + + + + SW6 + + SW6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW1 + + SW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D4 + + D4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D2 + + D2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW3 + + SW3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW2 + + SW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D1 + + D1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW9 + + SW9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW5 + + SW5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D6 + + D6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW7 + + SW7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW4 + + SW4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D5 + + D5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D7 + + D7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D3 + + D3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW8 + + SW8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D8 + + D8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D9 + + D9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW2 + + ROW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL1 + + + COL1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW1 + + ROW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL2 + + + COL2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL0 + + + COL0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW0 + + ROW0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW4 + + SW4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D1 + + D1 + + + + + + + + + + + + + + + + + + + + + + + + + SW1 + + SW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D4 + + D4 + + + + + + + + + + + + + + + + + + + + + + + SW9 + + SW9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D6 + + D6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D5 + + D5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW8 + + SW8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D8 + + D8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D9 + + D9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D7 + + D7 + + + + + + + + + + + + + + + + + + + + + + SW7 + + SW7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW2 + + SW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D2 + + D2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW3 + + SW3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW5 + + SW5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D3 + + D3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW6 + + SW6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/services/input/diodes-rc.svg b/doc/services/input/diodes-rc.svg new file mode 100644 index 000000000000000..91e0f9607ab4c6e --- /dev/null +++ b/doc/services/input/diodes-rc.svg @@ -0,0 +1,6140 @@ + + + + SVG Image created as keyboard-matrix-testboard-diodes-rc.svg date 2023/12/18 09:58:32 + Image generated by Eeschema-SVG + + + + + + + + + + + + + + + + + + + + + + + + + SW7 + + SW7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW2 + + SW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D3 + + D3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D2 + + D2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D6 + + D6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW3 + + SW3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D5 + + D5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW1 + + SW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D1 + + D1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW4 + + SW4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D4 + + D4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D7 + + D7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW5 + + SW5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D9 + + D9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW6 + + SW6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW9 + + SW9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D8 + + D8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW8 + + SW8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL0 + + + COL0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW0 + + ROW0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW1 + + ROW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW2 + + ROW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL2 + + + COL2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL1 + + + COL1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW8 + + SW8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D8 + + D8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW9 + + SW9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW6 + + SW6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D9 + + D9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW5 + + SW5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D7 + + D7 + + + + + + + + + + + + + + + + + + + + + + SW7 + + SW7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D4 + + D4 + + + + + + + + + + + + + + + + + + + + + + + SW4 + + SW4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D1 + + D1 + + + + + + + + + + + + + + + + + + + + + + + + + SW1 + + SW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D5 + + D5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW3 + + SW3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D6 + + D6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D2 + + D2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D3 + + D3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW2 + + SW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/services/input/gpio-kbd.rst b/doc/services/input/gpio-kbd.rst new file mode 100644 index 000000000000000..2910405bdd28e3c --- /dev/null +++ b/doc/services/input/gpio-kbd.rst @@ -0,0 +1,240 @@ +.. _gpio-kbd: + +GPIO Keyboard Matrix +#################### + +The :dtcompatible:`gpio-kbd-matrix` driver supports a large variety of keyboard +matrix hardware configurations and has numerous options to change its behavior. +This is an overview of some common setups and how they can be supported by the +driver. + +The conventional configuration for all of these is that the driver reads on the +row GPIOs (inputs) and selects on the columns GPIOs (output). + +Base use case, no isolation diodes, interrupt capable GPIOs +*********************************************************** + +This is the common configuration found on consumer keyboards with membrane +switches and flexible circuit boards, no isolation diodes, requires ghosting +detection (which is enabled by default). + +.. figure:: no-diodes.svg + :align: center + :width: 50% + + A 3x3 matrix, no diodes + +The system must support GPIO interrupts, and the interrupt can be enabled on all +row GPIOs at the same time. + +.. code-block:: devicetree + + kbd-matrix { + compatible = "gpio-kbd-matrix"; + row-gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, + <&gpio0 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, + <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + col-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>, + <&gpio0 4 GPIO_ACTIVE_LOW>, + <&gpio0 5 GPIO_ACTIVE_LOW>; + }; + +In this configuration the matrix scanning library enters idle mode once all +keys are released, and the keyboard matrix thread only wakes up when a key has +been pressed. + +GPIOs for columns that are not currently selected are configured in high +impedance mode. This means that the row state may need some time to settle to +avoid misreading the key state from a column to the following one. The settle +time can be tweaked by changing the ``settle-time-us`` property. + +Isolation diodes +**************** + +If the matrix has isolation diodes for every key, then it's possible to: + + - disable ghosting detection, allowing any key combination to be detected + - configuring the driver to drive unselected columns GPIO to inactive state + rather than high impedance, this allows to reduce the settle time + (potentially down to 0), and use the more efficient port wide GPIO read APIs + (happens automatically if the GPIO pins are sequential) + +Matrixes with diodes going from rows to columns must use pull-ups on rows and +active low columns. + +.. figure:: diodes-rc.svg + :align: center + :width: 50% + + A 3x3 matrix with row to column isolation diodes. + +.. code-block:: devicetree + + kbd-matrix { + compatible = "gpio-kbd-matrix"; + row-gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, + <&gpio0 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>, + <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + col-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>, + <&gpio0 4 GPIO_ACTIVE_LOW>, + <&gpio0 5 GPIO_ACTIVE_LOW>; + col-drive-inactive; + settle-time-us = <0>; + no-ghostkey-check; + }; + +Matrixes with diodes going from columns to rows must use pull-downs on rows and +active high columns. + +.. figure:: diodes-cr.svg + :align: center + :width: 50% + + A 3x3 matrix with column to row isolation diodes. + +.. code-block:: devicetree + + kbd-matrix { + compatible = "gpio-kbd-matrix"; + row-gpios = <&gpio0 0 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpio0 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpio0 2 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + col-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>, + <&gpio0 4 GPIO_ACTIVE_HIGH>, + <&gpio0 5 GPIO_ACTIVE_HIGH>; + col-drive-inactive; + settle-time-us = <0>; + no-ghostkey-check; + }; + +GPIO with no interrupt support +****************************** + +Some GPIO controllers have limitations on GPIO interrupts, and may not support +enabling interrupts on all row GPIOs at the same time. + +In this case, the driver can be configured to not use interrupt at all, and +instead idle by selecting all columns and keep polling on the row GPIOs, which +is a single GPIO API operation if the pins are sequential. + +This configuration can be enabled by setting the ``idle-mode`` property to +``poll``: + +.. code-block:: devicetree + + kbd-matrix { + compatible = "gpio-kbd-matrix"; + ... + idle-mode = "poll"; + }; + +GPIO multiplexer +**************** + +In more extreme cases, such as if the columns are using a multiplexer and it's +impossible to select all of them at the same time, the driver can be configured +to scan continuously. + +This can be done by setting ``idle-mode`` to ``scan`` and ``poll-timeout-ms`` +to ``0``. + +.. code-block:: devicetree + + kbd-matrix { + compatible = "gpio-kbd-matrix"; + ... + poll-timeout-ms = <0>; + idle-mode = "scan"; + }; + +Row and column GPIO selection +***************************** + +If the row GPIOs are sequential and on the same gpio controller, the driver +automatically switches API to read from the whole GPIO port rather than the +individual pins. This is particularly useful if the GPIOs are not memory +mapped, for example on an I2C or SPI port expander, as this significantly +reduces the number of transactions on the corresponding bus. + +The same is true for column GPIOs, but only if the matrix is configured for +``col-drive-inactive``, so that is only usable for matrixes with isolation +diodes. + +16-bit row support +****************** + +The driver uses an 8-bit datatype to store the row state by default, which +limits the matrix row size to 8. This can be increased to 16 by enabling the +:kconfig:option:`CONFIG_INPUT_KBD_MATRIX_16_BIT_ROW` option. + +Actual key mask configuration +***************************** + +If the key matrix is not complete, a map of the keys that are actually +populated can be specified using the `actual-key-mask` property. This allows +the matrix state to be filtered to remove keys that are not present before +ghosting detection, potentially allowing key combinations that would otherwise +be blocked by it. + +For example for a 3x3 matrix missing a key: + +.. figure:: no-sw4.svg + :align: center + :width: 50% + + A 3x3 matrix missing a key. + +.. code-block:: devicetree + + kbd-matrix { + compatible = "gpio-kbd-matrix"; + ... + actual-key-mask = <0x07 0x05 0x07>; + }; + +This would allow, for example, to detect pressing ``Sw1``, ``SW2`` and ``SW4`` +at the same time without triggering anti ghosting. + +The actual key mask can be changed at runtime by enabling +:kconfig:option:`CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC` and the using the +:c:func:`input_kbd_matrix_actual_key_mask_set` API. + +Keyboard matrix shell commands +****************************** + +The shell command ``kbd_matrix_state_dump`` can be used to test the +functionality of any keyboard matrix driver implemented using the keyboard +matrix library. Once enabled it logs the state of the matrix every time it +changes, and once disabled it prints an or-mask of any key that has been +detected, which can be used to set the ``actual-key-mask`` property. + +The command can be enabled using the +:kconfig:option:`CONFIG_INPUT_SHELL_KBD_MATRIX_STATE`. + +Example usage: + +.. code-block:: console + + uart:~$ device list + devices: + - kbd-matrix (READY) + uart:~$ input kbd_matrix_state_dump kbd-matrix + Keyboard state logging enabled for kbd-matrix + [00:01:41.678,466] input: kbd-matrix state [01 -- -- --] (1) + [00:01:41.784,912] input: kbd-matrix state [-- -- -- --] (0) + ... + press more buttons + ... + uart:~$ input kbd_matrix_state_dump off + Keyboard state logging disabled + [00:01:47.967,651] input: kbd-matrix key-mask [07 05 07 --] (8) + +Keyboard matrix library +*********************** + +The GPIO keyboard matrix driver is based on a generic keyboard matrix library, +which implements the core functionalities such as scanning delays, debouncing, +idle mode etc. This can be reused to implement other keyboard matrix drivers, +potentially application specific. + +.. doxygengroup:: input_kbd_matrix diff --git a/doc/services/input/index.rst b/doc/services/input/index.rst index b18c57beb3057df..01d7d92b0887470 100644 --- a/doc/services/input/index.rst +++ b/doc/services/input/index.rst @@ -78,6 +78,15 @@ compatibility device node, for example: }; }; +Driver Documentation +******************** + +.. toctree:: + :maxdepth: 1 + + gpio-kbd.rst + + API Reference ************* @@ -88,7 +97,7 @@ Input Event Definitions .. doxygengroup:: input_events -Keyboard Matrix API Reference -***************************** +Analog Axis API Reference +************************* -.. doxygengroup:: input_kbd_matrix +.. doxygengroup:: input_analog_axis diff --git a/doc/services/input/no-diodes.svg b/doc/services/input/no-diodes.svg new file mode 100644 index 000000000000000..ced8ad7ce78ffae --- /dev/null +++ b/doc/services/input/no-diodes.svg @@ -0,0 +1,2689 @@ + + + + SVG Image created as keyboard-matrix-testboard-no-diodes.svg date 2023/12/18 09:58:32 + Image generated by Eeschema-SVG + + + + + + + + + + + + + + + + + + + + + + + + + SW4 + + SW4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW7 + + SW7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW8 + + SW8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW1 + + SW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW5 + + SW5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW9 + + SW9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW2 + + SW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW6 + + SW6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW3 + + SW3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW0 + + ROW0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW1 + + ROW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL2 + + + COL2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW2 + + ROW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL0 + + + COL0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL1 + + + COL1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/services/input/no-sw4.svg b/doc/services/input/no-sw4.svg new file mode 100644 index 000000000000000..b79188fbe923af4 --- /dev/null +++ b/doc/services/input/no-sw4.svg @@ -0,0 +1,2496 @@ + + + + SVG Image created as keyboard-matrix-testboard-no-sw4.svg date 2023/12/18 09:58:32 + Image generated by Eeschema-SVG + + + + + + + + + + + + + + + + + + + + + + + + + SW7 + + SW7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW3 + + SW3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW8 + + SW8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW1 + + SW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW6 + + SW6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW2 + + SW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW4 + + SW4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SW9 + + SW9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL2 + + + COL2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL0 + + + COL0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COL1 + + + COL1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW0 + + ROW0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW1 + + ROW1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ROW2 + + ROW2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 30b3e517cd51ce4..55a841dd565d3aa 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -25,8 +25,8 @@ Minimal Realtime System Profile (PSE51) :header: Symbol, Support, Remarks :widths: 50, 10, 50 - POSIX_C_LANG_JUMP,, - POSIX_C_LANG_SUPPORT, yes, :ref:`†` + POSIX_C_LANG_JUMP, yes, :ref:`POSIX_C_LANG_JUMP ` + POSIX_C_LANG_SUPPORT, yes, :ref:`POSIX_C_LANG_SUPPORT ` POSIX_DEVICE_IO,, :ref:`†` POSIX_FILE_LOCKING,, POSIX_SIGNALS,, :ref:`†` @@ -57,9 +57,6 @@ Minimal Realtime System Profile (PSE51) _POSIX_TIMEOUTS, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` _POSIX_TIMERS, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` -.. note:: - For PSE51 support, 44 of 75 symbols are currently implemented. - .. _posix_aep_pse52: Realtime Controller System Profile (PSE52) @@ -77,9 +74,9 @@ Realtime Controller System Profile (PSE52) :header: Symbol, Support, Remarks :widths: 50, 10, 50 - POSIX_C_LANG_JUMP,, - POSIX_C_LANG_MATH, yes, - POSIX_C_LANG_SUPPORT, yes, :ref:`†` + POSIX_C_LANG_JUMP, yes, :ref:`POSIX_C_LANG_JUMP ` + POSIX_C_LANG_MATH, yes, :ref:`POSIX_C_LANG_MATH ` + POSIX_C_LANG_SUPPORT, yes, :ref:`POSIX_C_LANG_SUPPORT ` POSIX_DEVICE_IO,, :ref:`†` POSIX_FD_MGMT,, POSIX_FILE_LOCKING,, @@ -134,9 +131,9 @@ Dedicated Realtime System Profile (PSE53) :header: Symbol, Support, Remarks :widths: 50, 10, 50 - POSIX_C_LANG_JUMP,, - POSIX_C_LANG_MATH, yes, - POSIX_C_LANG_SUPPORT, yes, :ref:`†` + POSIX_C_LANG_JUMP, yes, :ref:`POSIX_C_LANG_JUMP ` + POSIX_C_LANG_MATH, yes, :ref:`POSIX_C_LANG_MATH ` + POSIX_C_LANG_SUPPORT, yes, :ref:`POSIX_C_LANG_SUPPORT ` POSIX_DEVICE_IO,, :ref:`†` POSIX_FD_MGMT,, POSIX_FILE_LOCKING,, diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 7d28efcf9acf150..53f3113ca68fbc2 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -14,6 +14,13 @@ As per `IEEE 1003.1-2017`, this section details Zephyr's POSIX conformance. Zephyr's current design, some features requiring multi-process capabilities may exhibit undefined behaviour, which we denote with the † (obelus) symbol. +.. _posix_libc_provided: + +.. note:: + Features listed in various POSIX Options or Option Groups may be provided in whole or in part + by a conformant C library implementation. This includes (but is not limited to) POSIX + Extensions to the ISO C Standard (`CX`_). + .. _posix_system_interfaces: POSIX System Interfaces @@ -61,7 +68,7 @@ POSIX System Interfaces _POSIX_REALTIME_SIGNALS, -1, :ref:`†` :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` - _POSIX_THREAD_SAFE_FUNCTIONS, 200809L, + :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, :ref:`_POSIX_THREADS`, -1, :kconfig:option:`CONFIG_PTHREAD_IPC` :ref:`_POSIX_TIMEOUTS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` :ref:`_POSIX_TIMERS`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` @@ -143,3 +150,5 @@ XSI System Interfaces :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` _POSIX_THREAD_PROCESS_SHARED, -1, + +.. _CX: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap01.html diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index 893754f647d1381..47fc9ebd0f9e894 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -102,123 +102,54 @@ This table lists service support status in Zephyr: pthread_getconcurrency(),yes pthread_setconcurrency(),yes +.. _posix_option_group_c_lang_jump: + +POSIX_C_LANG_JUMP +================= + +The ``POSIX_C_LANG_JUMP`` Option Group is included in the ISO C standard. + +.. note:: + When using Newlib, Picolibc, or other C libraries conforming to the ISO C Standard, the + ``POSIX_C_LANG_JUMP`` Option Group is considered supported. + +.. csv-table:: POSIX_C_LANG_JUMP + :header: API, Supported + :widths: 50,10 + + setjmp(), yes + longjmp(), yes + +.. _posix_option_group_c_lang_math: + +POSIX_C_LANG_MATH +================= + +The ``POSIX_C_LANG_MATH`` Option Group is included in the ISO C standard. + +.. note:: + When using Newlib, Picolibc, or other C libraries conforming to the ISO C Standard, the + ``POSIX_C_LANG_MATH`` Option Group is considered supported. + +Please refer to `Subprofiling Considerations`_ for details on the ``POSIX_C_LANG_MATH`` Option +Group. + .. _posix_option_group_c_lang_support: POSIX_C_LANG_SUPPORT ==================== -The POSIX_C_LANG_SUPPORT option group contains the general ISO C -Library. +The POSIX_C_LANG_SUPPORT option group contains the general ISO C Library. -.. csv-table:: POSIX_C_LANG_SUPPORT - :header: API, Supported - :widths: 50,10 +.. note:: + When using Newlib, Picolibc, or other C libraries conforming to the ISO C Standard, the entire + ``POSIX_C_LANG_SUPPORT`` Option Group is considered supported. - abs(),yes - asctime(), - asctime_r(), - atof(), - atoi(),yes - atol(), - atoll(), - bsearch(),yes - calloc(),yes - ctime(), - ctime_r(), - difftime(), - div(), - feclearexcept(), - fegetenv(), - fegetexceptflag(), - fegetround(), - feholdexcept(), - feraiseexcept(), - fesetenv(), - fesetexceptflag(), - fesetround(), - fetestexcept(), - feupdateenv(), - free(),yes - gmtime(),yes - gmtime_r(),yes - imaxabs(), - imaxdiv(), - isalnum(),yes - isalpha(),yes - isblank(), - iscntrl(),yes - isdigit(),yes - isgraph(),yes - islower(), - isprint(),yes - ispunct(), - isspace(),yes - isupper(),yes - isxdigit(),yes - labs(),yes - ldiv(), - llabs(),yes - lldiv(), - localeconv(), - localtime(),yes - localtime_r(), - malloc(),yes - memchr(),yes - memcmp(),yes - memcpy(),yes - memmove(),yes - memset(),yes - mktime(),yes - qsort(),yes - rand(),yes - rand_r(),yes - realloc(),yes - setlocale(), - snprintf(),yes - sprintf(),yes - srand(),yes - sscanf(), - strcat(),yes - strchr(),yes - strcmp(),yes - strcoll(), - strcpy(),yes - strcspn(),yes - strerror(),yes - strerror_r(),yes - strftime(), - strlen(),yes - strncat(),yes - strncmp(),yes - strncpy(),yes - strpbrk(), - strrchr(),yes - strspn(),yes - strstr(),yes - strtod(), - strtof(), - strtoimax(), - strtok(),yes - strtok_r(),yes - strtol(),yes - strtold(), - strtoll(),yes - strtoul(),yes - strtoull(),yes - strtoumax(), - strxfrm(), - time(),yes - tolower(),yes - toupper(),yes - tzname(), - tzset(), - va_arg(),yes - va_copy(),yes - va_end(),yes - va_start(),yes - vsnprintf(),yes - vsprintf(),yes - vsscanf(), +Please refer to `Subprofiling Considerations`_ for details on the ``POSIX_C_LANG_SUPPORT`` Option +Group. + +For more information on developing Zephyr applications in the C programming language, please refer +to :ref:`details`. .. _posix_option_group_single_process: @@ -367,14 +298,14 @@ POSIX_SEMAPHORES :header: API, Supported :widths: 50,10 - sem_close(), + sem_close(),yes sem_destroy(),yes sem_getvalue(),yes sem_init(),yes - sem_open(), + sem_open(),yes sem_post(),yes sem_trywait(),yes - sem_unlink(), + sem_unlink(),yes sem_wait(),yes .. _posix_option_group_spin_locks: @@ -517,6 +448,35 @@ _POSIX_THREAD_PRIORITY_SCHEDULING pthread_setschedparam(),yes pthread_setschedprio(),yes +.. _posix_thread_safe_functions: + +_POSIX_THREAD_SAFE_FUNCTIONS +++++++++++++++++++++++++++++ + +.. csv-table:: _POSIX_THREAD_SAFE_FUNCTIONS + :header: API, Supported + :widths: 50,10 + + asctime_r(), + ctime_r(), + flockfile(), + ftrylockfile(), + funlockfile(), + getc_unlocked(), yes + getchar_unlocked(), yes + getgrgid_r(), + getgrnam_r(), + getpwnam_r(), + getpwuid_r(), + gmtime_r(), yes + localtime_r(), + putc_unlocked(), yes + putchar_unlocked(), yes + rand_r(), yes + readdir_r(), + strerror_r(), yes + strtok_r(), yes + .. _posix_option_timeouts: _POSIX_TIMEOUTS @@ -551,3 +511,7 @@ _XOPEN_STREAMS isastream(), putmsg(), putpmsg(), + + +.. _Subprofiling Considerations: + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html diff --git a/doc/services/portability/posix/overview/index.rst b/doc/services/portability/posix/overview/index.rst index 56810e49ac1419b..384e7c142c05c85 100644 --- a/doc/services/portability/posix/overview/index.rst +++ b/doc/services/portability/posix/overview/index.rst @@ -59,7 +59,9 @@ as part of `IEEE 1003.13-2003`_ (also known as POSIX.13-2003). POSIX.13-2003 AEP were formalized in 2003 via "Units of Functionality" but the specification is now inactive (for reference only). Nevertheless, the intent is still captured as part of POSIX-1.2017 -via :ref:`Options` and :ref:`Option Groups`, in Appendix E. +via :ref:`Options` and :ref:`Option Groups`. + +For more information, please see `IEEE 1003.1-2017, Section E, Subprofiling Considerations`_. .. _posix_apps: @@ -133,3 +135,5 @@ Alternatively, users may enable one of the Kconfig options below as a shortcut t .. _IEEE Computer Society: https://www.computer.org/ .. _IEEE 1003.1-2017: https://standards.ieee.org/ieee/1003.1/7101/ .. _IEEE 1003.13-2003: https://standards.ieee.org/ieee/1003.13/3322/ +.. _IEEE 1003.1-2017, Section E, Subprofiling Considerations: + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html diff --git a/drivers/adc/adc_nrfx_saadc.c b/drivers/adc/adc_nrfx_saadc.c index 72a20f47fc9f015..6d1973ca0aae9c2 100644 --- a/drivers/adc/adc_nrfx_saadc.c +++ b/drivers/adc/adc_nrfx_saadc.c @@ -170,7 +170,7 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx, if (!repeat) { nrf_saadc_buffer_pointer_set( NRF_SAADC, - nrf_saadc_buffer_pointer_get(NRF_SAADC) + + (uint16_t *)nrf_saadc_buffer_pointer_get(NRF_SAADC) + nrf_saadc_amount_get(NRF_SAADC)); } } @@ -256,7 +256,7 @@ static int check_buffer_size(const struct adc_sequence *sequence, { size_t needed_buffer_size; - needed_buffer_size = active_channels * sizeof(nrf_saadc_value_t); + needed_buffer_size = active_channels * sizeof(uint16_t); if (sequence->options) { needed_buffer_size *= (1 + sequence->options->extra_samplings); } diff --git a/drivers/bluetooth/hci/CMakeLists.txt b/drivers/bluetooth/hci/CMakeLists.txt index e20706c494fe2c5..adda6ea0e2ab05a 100644 --- a/drivers/bluetooth/hci/CMakeLists.txt +++ b/drivers/bluetooth/hci/CMakeLists.txt @@ -19,7 +19,13 @@ zephyr_library_sources_ifdef(CONFIG_BT_ESP32 hci_esp32.c) zephyr_library_sources_ifdef(CONFIG_BT_H4 h4.c) zephyr_library_sources_ifdef(CONFIG_BT_H5 h5.c) zephyr_library_sources_ifdef(CONFIG_BT_HCI_IPC ipc.c) -zephyr_library_sources_ifdef(CONFIG_BT_SPI spi.c) +if(CONFIG_BT_SPI) + if ((CONFIG_DT_HAS_ST_HCI_SPI_V1_ENABLED) OR (CONFIG_DT_HAS_ST_HCI_SPI_V2_ENABLED)) + zephyr_library_sources(hci_spi_st.c) + else() + zephyr_library_sources(spi.c) + endif() +endif() zephyr_library_sources_ifdef(CONFIG_BT_STM32_IPM ipm_stm32wb.c) zephyr_library_sources_ifdef(CONFIG_BT_STM32WBA hci_stm32wba.c) zephyr_library_sources_ifdef(CONFIG_BT_USERCHAN userchan.c) diff --git a/drivers/bluetooth/hci/hci_spi_st.c b/drivers/bluetooth/hci/hci_spi_st.c new file mode 100644 index 000000000000000..bd1e4d447ef3d32 --- /dev/null +++ b/drivers/bluetooth/hci/hci_spi_st.c @@ -0,0 +1,614 @@ +/* hci_spi_st.c - STMicroelectronics HCI SPI Bluetooth driver */ + +/* + * Copyright (c) 2017 Linaro Ltd. + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if defined(CONFIG_DT_HAS_ST_HCI_SPI_V1_ENABLED) +#define DT_DRV_COMPAT st_hci_spi_v1 + +#elif defined(CONFIG_DT_HAS_ST_HCI_SPI_V2_ENABLED) +#define DT_DRV_COMPAT st_hci_spi_v2 + +#endif /* CONFIG_DT_HAS_ST_HCI_SPI_V1_ENABLED */ + +#include +#include +#include +#include +#include + +#include +#include + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include +LOG_MODULE_REGISTER(bt_driver); + +#define HCI_CMD 0x01 +#define HCI_ACL 0x02 +#define HCI_SCO 0x03 +#define HCI_EVT 0x04 +/* ST Proprietary extended event */ +#define HCI_EXT_EVT 0x82 + +/* Special Values */ +#define SPI_WRITE 0x0A +#define SPI_READ 0x0B +#define READY_NOW 0x02 + +#define EVT_BLUE_INITIALIZED 0x01 + +/* Offsets */ +#define STATUS_HEADER_READY 0 +#define STATUS_HEADER_TOREAD 3 +#define STATUS_HEADER_TOWRITE 1 + +#define PACKET_TYPE 0 +#define EVT_HEADER_TYPE 0 +#define EVT_HEADER_EVENT 1 +#define EVT_HEADER_SIZE 2 +#define EVT_LE_META_SUBEVENT 3 +#define EVT_VENDOR_CODE_LSB 3 +#define EVT_VENDOR_CODE_MSB 4 + +#define CMD_OGF 1 +#define CMD_OCF 2 + +#define SPI_MAX_MSG_LEN 255 + +/* Single byte header denoting the buffer type */ +#define H4_HDR_SIZE 1 + +/* Maximum L2CAP MTU that can fit in a single packet */ +#define MAX_MTU (SPI_MAX_MSG_LEN - H4_HDR_SIZE - BT_L2CAP_HDR_SIZE - BT_HCI_ACL_HDR_SIZE) + +#if CONFIG_BT_L2CAP_TX_MTU > MAX_MTU +#warning CONFIG_BT_L2CAP_TX_MTU is too large and can result in packets that cannot \ + be transmitted across this HCI link +#endif /* CONFIG_BT_L2CAP_TX_MTU > MAX_MTU */ + +static uint8_t rxmsg[SPI_MAX_MSG_LEN]; +static uint8_t txmsg[SPI_MAX_MSG_LEN]; + +static const struct gpio_dt_spec irq_gpio = GPIO_DT_SPEC_INST_GET(0, irq_gpios); +static const struct gpio_dt_spec rst_gpio = GPIO_DT_SPEC_INST_GET(0, reset_gpios); + +static struct gpio_callback gpio_cb; + +static K_SEM_DEFINE(sem_initialised, 0, 1); +static K_SEM_DEFINE(sem_request, 0, 1); +static K_SEM_DEFINE(sem_busy, 1, 1); + +static K_KERNEL_STACK_DEFINE(spi_rx_stack, CONFIG_BT_DRV_RX_STACK_SIZE); +static struct k_thread spi_rx_thread_data; + +#if defined(CONFIG_BT_BLUENRG_ACI) +#define BLUENRG_ACI_WRITE_CONFIG_DATA BT_OP(BT_OGF_VS, 0x000C) +#define BLUENRG_CONFIG_PUBADDR_OFFSET 0x00 +#define BLUENRG_CONFIG_PUBADDR_LEN 0x06 +#define BLUENRG_CONFIG_LL_ONLY_OFFSET 0x2C +#define BLUENRG_CONFIG_LL_ONLY_LEN 0x01 + +static int bt_spi_send_aci_config(uint8_t offset, const uint8_t *value, size_t value_len); +#endif /* CONFIG_BT_BLUENRG_ACI */ + +static const struct spi_dt_spec bus = SPI_DT_SPEC_INST_GET( + 0, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 0); + +static struct spi_buf spi_tx_buf; +static struct spi_buf spi_rx_buf; +static const struct spi_buf_set spi_tx = { + .buffers = &spi_tx_buf, + .count = 1 +}; +static const struct spi_buf_set spi_rx = { + .buffers = &spi_rx_buf, + .count = 1 +}; + +struct bt_hci_ext_evt_hdr { + uint8_t evt; + uint16_t len; +} __packed; + +static inline int bt_spi_transceive(void *tx, uint32_t tx_len, + void *rx, uint32_t rx_len) +{ + spi_tx_buf.buf = tx; + spi_tx_buf.len = (size_t)tx_len; + spi_rx_buf.buf = rx; + spi_rx_buf.len = (size_t)rx_len; + return spi_transceive_dt(&bus, &spi_tx, &spi_rx); +} + +static inline uint16_t bt_spi_get_cmd(uint8_t *msg) +{ + return (msg[CMD_OCF] << 8) | msg[CMD_OGF]; +} + +static inline uint16_t bt_spi_get_evt(uint8_t *msg) +{ + return (msg[EVT_VENDOR_CODE_MSB] << 8) | msg[EVT_VENDOR_CODE_LSB]; +} + +static void bt_spi_isr(const struct device *unused1, + struct gpio_callback *unused2, + uint32_t unused3) +{ + LOG_DBG(""); + + k_sem_give(&sem_request); +} + +static bool bt_spi_handle_vendor_evt(uint8_t *msg) +{ + bool handled = false; + + switch (bt_spi_get_evt(msg)) { + case EVT_BLUE_INITIALIZED: { + k_sem_give(&sem_initialised); +#if defined(CONFIG_BT_BLUENRG_ACI) + /* force BlueNRG to be on controller mode */ + uint8_t data = 1; + + bt_spi_send_aci_config(BLUENRG_CONFIG_LL_ONLY_OFFSET, &data, 1); +#endif + handled = true; + } + default: + break; + } + return handled; +} + +#define IS_IRQ_HIGH gpio_pin_get_dt(&irq_gpio) + +#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) + +/* Define a limit when reading IRQ high */ +#define IRQ_HIGH_MAX_READ 15 + +/* On BlueNRG-MS, host is expected to read */ +/* as long as IRQ pin is high */ +#define READ_CONDITION IS_IRQ_HIGH + +static void assert_cs(void) +{ + gpio_pin_set_dt(&bus.config.cs.gpio, 0); + gpio_pin_set_dt(&bus.config.cs.gpio, 1); +} + +static void release_cs(bool data_transaction) +{ + ARG_UNUSED(data_transaction); + gpio_pin_set_dt(&bus.config.cs.gpio, 0); +} + +static int bt_spi_get_header(uint8_t op, uint16_t *size) +{ + uint8_t header_master[5] = {op, 0, 0, 0, 0}; + uint8_t header_slave[5]; + uint8_t size_offset, attempts; + int ret; + + if (op == SPI_READ) { + if (!IS_IRQ_HIGH) { + *size = 0; + return 0; + } + size_offset = STATUS_HEADER_TOREAD; + } else if (op == SPI_WRITE) { + size_offset = STATUS_HEADER_TOWRITE; + } else { + return -EINVAL; + } + attempts = IRQ_HIGH_MAX_READ; + do { + if (op == SPI_READ) { + /* Keep checking that IRQ is still high, if we need to read */ + if (!IS_IRQ_HIGH) { + *size = 0; + return 0; + } + } + assert_cs(); + ret = bt_spi_transceive(header_master, 5, header_slave, 5); + if (ret) { + /* SPI transaction failed */ + break; + } + + *size = (header_slave[STATUS_HEADER_READY] == READY_NOW) ? + header_slave[size_offset] : 0; + attempts--; + } while ((*size == 0) && attempts); + + return ret; +} + +#elif DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) + +#define READ_CONDITION false + +static void assert_cs(uint16_t delay) +{ + gpio_pin_set_dt(&bus.config.cs.gpio, 0); + if (delay) { + k_sleep(K_USEC(delay)); + } + gpio_pin_set_dt(&bus.config.cs.gpio, 1); + gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_DISABLE); +} + +static void release_cs(bool data_transaction) +{ + /* Consume possible event signals */ + while (k_sem_take(&sem_request, K_NO_WAIT) == 0) { + } + if (data_transaction) { + /* Wait for IRQ to become low only when data phase has been performed */ + while (IS_IRQ_HIGH) { + } + } + gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_TO_ACTIVE); + gpio_pin_set_dt(&bus.config.cs.gpio, 0); +} + +static int bt_spi_get_header(uint8_t op, uint16_t *size) +{ + uint8_t header_master[5] = {op, 0, 0, 0, 0}; + uint8_t header_slave[5]; + uint16_t cs_delay; + uint8_t size_offset; + int ret; + + if (op == SPI_READ) { + if (!IS_IRQ_HIGH) { + *size = 0; + return 0; + } + cs_delay = 0; + size_offset = STATUS_HEADER_TOREAD; + } else if (op == SPI_WRITE) { + /* To make sure we have a minimum delay from previous release cs */ + cs_delay = 100; + size_offset = STATUS_HEADER_TOWRITE; + } else { + return -EINVAL; + } + + assert_cs(cs_delay); + /* Wait up to a maximum time of 100 ms */ + if (!WAIT_FOR(IS_IRQ_HIGH, 100000, k_usleep(100))) { + LOG_ERR("IRQ pin did not raise"); + return -EIO; + } + + ret = bt_spi_transceive(header_master, 5, header_slave, 5); + *size = header_slave[size_offset] | (header_slave[size_offset + 1] << 8); + return ret; +} +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) */ + +#if defined(CONFIG_BT_BLUENRG_ACI) +static int bt_spi_send_aci_config(uint8_t offset, const uint8_t *value, size_t value_len) +{ + struct net_buf *buf; + uint8_t *cmd_data; + size_t data_len = 2 + value_len; + + buf = bt_hci_cmd_create(BLUENRG_ACI_WRITE_CONFIG_DATA, data_len); + if (!buf) { + return -ENOBUFS; + } + + cmd_data = net_buf_add(buf, data_len); + cmd_data[0] = offset; + cmd_data[1] = value_len; + memcpy(&cmd_data[2], value, value_len); + + return bt_hci_cmd_send(BLUENRG_ACI_WRITE_CONFIG_DATA, buf); +} + +static int bt_spi_bluenrg_setup(const struct bt_hci_setup_params *params) +{ + int ret; + const bt_addr_t *addr = ¶ms->public_addr; + + if (!bt_addr_eq(addr, BT_ADDR_NONE) && !bt_addr_eq(addr, BT_ADDR_ANY)) { + ret = bt_spi_send_aci_config( + BLUENRG_CONFIG_PUBADDR_OFFSET, + addr->val, sizeof(addr->val)); + + if (ret != 0) { + LOG_ERR("Failed to set BlueNRG public address (%d)", ret); + return ret; + } + } + + return 0; +} +#endif /* CONFIG_BT_BLUENRG_ACI */ + +static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg) +{ + bool discardable = false; + k_timeout_t timeout = K_FOREVER; + struct bt_hci_acl_hdr acl_hdr; + struct net_buf *buf; + int len; + + switch (msg[PACKET_TYPE]) { +#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) + case HCI_EXT_EVT: + struct bt_hci_ext_evt_hdr *evt = (struct bt_hci_ext_evt_hdr *) (msg + 1); + struct bt_hci_evt_hdr *evt2 = (struct bt_hci_evt_hdr *) (msg + 1); + + if (evt->len > 0xff) { + return NULL; + } + /* Use memmove instead of memcpy due to buffer overlapping */ + memmove(msg + (1 + sizeof(*evt2)), msg + (1 + sizeof(*evt)), evt2->len); + /* Manage event as regular HCI_EVT */ + __fallthrough; +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) */ + case HCI_EVT: + switch (msg[EVT_HEADER_EVENT]) { + case BT_HCI_EVT_VENDOR: + /* Run event through interface handler */ + if (bt_spi_handle_vendor_evt(msg)) { + return NULL; + } + /* Event has not yet been handled */ + __fallthrough; + default: + if (msg[EVT_HEADER_EVENT] == BT_HCI_EVT_LE_META_EVENT && + (msg[EVT_LE_META_SUBEVENT] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { + discardable = true; + timeout = K_NO_WAIT; + } + buf = bt_buf_get_evt(msg[EVT_HEADER_EVENT], + discardable, timeout); + if (!buf) { + LOG_DBG("Discard adv report due to insufficient buf"); + return NULL; + } + } + + len = sizeof(struct bt_hci_evt_hdr) + msg[EVT_HEADER_SIZE]; + if (len > net_buf_tailroom(buf)) { + LOG_ERR("Event too long: %d", len); + net_buf_unref(buf); + return NULL; + } + net_buf_add_mem(buf, &msg[1], len); + break; + case HCI_ACL: + buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER); + memcpy(&acl_hdr, &msg[1], sizeof(acl_hdr)); + len = sizeof(acl_hdr) + sys_le16_to_cpu(acl_hdr.len); + if (len > net_buf_tailroom(buf)) { + LOG_ERR("ACL too long: %d", len); + net_buf_unref(buf); + return NULL; + } + net_buf_add_mem(buf, &msg[1], len); + break; + default: + LOG_ERR("Unknown BT buf type %d", msg[0]); + return NULL; + } + + return buf; +} + +static void bt_spi_rx_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct net_buf *buf; + uint16_t size = 0U; + int ret; + + (void)memset(&txmsg, 0xFF, SPI_MAX_MSG_LEN); + while (true) { + + /* Wait for interrupt pin to be active */ + k_sem_take(&sem_request, K_FOREVER); + + LOG_DBG(""); + + do { + /* Wait for SPI bus to be available */ + k_sem_take(&sem_busy, K_FOREVER); + ret = bt_spi_get_header(SPI_READ, &size); + + /* Read data */ + if (ret == 0 && size != 0) { + ret = bt_spi_transceive(&txmsg, size, &rxmsg, size); + } + + release_cs(size > 0); + + k_sem_give(&sem_busy); + + if (ret || size == 0) { + if (ret) { + LOG_ERR("Error %d", ret); + } + continue; + } + + LOG_HEXDUMP_DBG(rxmsg, size, "SPI RX"); + + /* Construct net_buf from SPI data */ + buf = bt_spi_rx_buf_construct(rxmsg); + if (buf) { + /* Handle the received HCI data */ + bt_recv(buf); + } + } while (READ_CONDITION); + } +} + +static int bt_spi_send(struct net_buf *buf) +{ + uint16_t size; + uint8_t rx_first[1]; + int ret; + + LOG_DBG(""); + + /* Buffer needs an additional byte for type */ + if (buf->len >= SPI_MAX_MSG_LEN) { + LOG_ERR("Message too long (%d)", buf->len); + return -EINVAL; + } + + switch (bt_buf_get_type(buf)) { + case BT_BUF_ACL_OUT: + net_buf_push_u8(buf, HCI_ACL); + break; + case BT_BUF_CMD: + net_buf_push_u8(buf, HCI_CMD); + break; + default: + LOG_ERR("Unsupported type"); + return -EINVAL; + } + + /* Wait for SPI bus to be available */ + k_sem_take(&sem_busy, K_FOREVER); + + ret = bt_spi_get_header(SPI_WRITE, &size); + size = MIN(buf->len, size); + + if (size < buf->len) { + LOG_WRN("Unable to write full data, skipping"); + size = 0; + ret = -ECANCELED; + } + + if (!ret) { + /* Transmit the message */ + ret = bt_spi_transceive(buf->data, size, + rx_first, 1); + } + + release_cs(size > 0); + + k_sem_give(&sem_busy); + + if (ret) { + LOG_ERR("Error %d", ret); + return ret; + } + + LOG_HEXDUMP_DBG(buf->data, buf->len, "SPI TX"); + +#if (DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) || DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2)) + /* + * Since a RESET has been requested, the chip will now restart. + * Unfortunately the BlueNRG will reply with "reset received" but + * since it does not send back a NOP, we have no way to tell when the + * RESET has actually taken place. Instead, we use the vendor command + * EVT_BLUE_INITIALIZED as an indication that it is safe to proceed. + */ + if (bt_spi_get_cmd(buf->data) == BT_HCI_OP_RESET) { + k_sem_take(&sem_initialised, K_FOREVER); + } +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) || DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) */ + net_buf_unref(buf); + + return ret; +} + +static int bt_spi_open(void) +{ + int err; + + /* Configure RST pin and hold BLE in Reset */ + err = gpio_pin_configure_dt(&rst_gpio, GPIO_OUTPUT_ACTIVE); + if (err) { + return err; + } + + /* Configure IRQ pin and the IRQ call-back/handler */ + err = gpio_pin_configure_dt(&irq_gpio, GPIO_INPUT); + if (err) { + return err; + } + + gpio_init_callback(&gpio_cb, bt_spi_isr, BIT(irq_gpio.pin)); + err = gpio_add_callback(irq_gpio.port, &gpio_cb); + if (err) { + return err; + } + + /* Enable the interrupt line */ + err = gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (err) { + return err; + } + + /* Take BLE out of reset */ + k_sleep(K_MSEC(DT_INST_PROP_OR(0, reset_assert_duration_ms, 0))); + gpio_pin_set_dt(&rst_gpio, 0); + + /* Start RX thread */ + k_thread_create(&spi_rx_thread_data, spi_rx_stack, + K_KERNEL_STACK_SIZEOF(spi_rx_stack), + bt_spi_rx_thread, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), + 0, K_NO_WAIT); + + /* Device will let us know when it's ready */ + k_sem_take(&sem_initialised, K_FOREVER); + + return 0; +} + +static const struct bt_hci_driver drv = { + .name = DEVICE_DT_NAME(DT_DRV_INST(0)), + .bus = BT_HCI_DRIVER_BUS_SPI, +#if defined(CONFIG_BT_BLUENRG_ACI) + .quirks = BT_QUIRK_NO_RESET, + .setup = bt_spi_bluenrg_setup, +#endif /* CONFIG_BT_BLUENRG_ACI */ + .open = bt_spi_open, + .send = bt_spi_send, +}; + +static int bt_spi_init(void) +{ + + if (!spi_is_ready_dt(&bus)) { + LOG_ERR("SPI device not ready"); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&irq_gpio)) { + LOG_ERR("IRQ GPIO device not ready"); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&rst_gpio)) { + LOG_ERR("Reset GPIO device not ready"); + return -ENODEV; + } + + bt_hci_driver_register(&drv); + + + LOG_DBG("BT SPI initialized"); + + return 0; +} + +SYS_INIT(bt_spi_init, POST_KERNEL, CONFIG_BT_SPI_INIT_PRIORITY); diff --git a/drivers/bluetooth/hci/spi.c b/drivers/bluetooth/hci/spi.c index afad8fcf2ba1c3e..5c2695435e4badb 100644 --- a/drivers/bluetooth/hci/spi.c +++ b/drivers/bluetooth/hci/spi.c @@ -86,16 +86,6 @@ static K_SEM_DEFINE(sem_busy, 1, 1); static K_KERNEL_STACK_DEFINE(spi_rx_stack, CONFIG_BT_DRV_RX_STACK_SIZE); static struct k_thread spi_rx_thread_data; -#if defined(CONFIG_BT_BLUENRG_ACI) -#define BLUENRG_ACI_WRITE_CONFIG_DATA BT_OP(BT_OGF_VS, 0x000C) -#define BLUENRG_CONFIG_PUBADDR_OFFSET 0x00 -#define BLUENRG_CONFIG_PUBADDR_LEN 0x06 -#define BLUENRG_CONFIG_LL_ONLY_OFFSET 0x2C -#define BLUENRG_CONFIG_LL_ONLY_LEN 0x01 - -static int bt_spi_send_aci_config(uint8_t offset, const uint8_t *value, size_t value_len); -#endif /* CONFIG_BT_BLUENRG_ACI */ - static const struct spi_dt_spec bus = SPI_DT_SPEC_INST_GET( 0, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 0); @@ -146,12 +136,6 @@ static bool bt_spi_handle_vendor_evt(uint8_t *msg) switch (bt_spi_get_evt(msg)) { case EVT_BLUE_INITIALIZED: { k_sem_give(&sem_initialised); -#if defined(CONFIG_BT_BLUENRG_ACI) - /* force BlueNRG to be on controller mode */ - uint8_t data = 1; - - bt_spi_send_aci_config(BLUENRG_CONFIG_LL_ONLY_OFFSET, &data, 1); -#endif handled = true; } default: @@ -160,144 +144,6 @@ static bool bt_spi_handle_vendor_evt(uint8_t *msg) return handled; } -#define IS_IRQ_HIGH gpio_pin_get_dt(&irq_gpio) - -#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) -/* Define a limit when reading IRQ high */ -/* It can be required to be increased for */ -/* some particular cases. */ -#define IRQ_HIGH_MAX_READ 3 -/* On BlueNRG-MS, host is expected to read */ -/* as long as IRQ pin is high */ -#define READ_CONDITION IS_IRQ_HIGH -/* We cannot retry write data without reading again the header */ -#define WRITE_DATA_CONDITION(...) true - -static void assert_cs(void) -{ - gpio_pin_set_dt(&bus.config.cs.gpio, 0); - gpio_pin_set_dt(&bus.config.cs.gpio, 1); -} - -static void release_cs(bool data_transaction) -{ - ARG_UNUSED(data_transaction); - gpio_pin_set_dt(&bus.config.cs.gpio, 0); -} - -static int bt_spi_get_header(uint8_t op, uint16_t *size) -{ - uint8_t header_master[5] = {op, 0, 0, 0, 0}; - uint8_t header_slave[5]; - uint8_t size_offset, attempts; - int ret; - - if (op == SPI_READ) { - if (!IS_IRQ_HIGH) { - *size = 0; - return 0; - } - size_offset = STATUS_HEADER_TOREAD; - } else if (op == SPI_WRITE) { - size_offset = STATUS_HEADER_TOWRITE; - } else { - return -EINVAL; - } - attempts = IRQ_HIGH_MAX_READ; - do { - if (op == SPI_READ) { - /* Keep checking that IRQ is still high, if we need to read */ - if (!IS_IRQ_HIGH) { - *size = 0; - return 0; - } - } - assert_cs(); - ret = bt_spi_transceive(header_master, 5, header_slave, 5); - if (ret) { - /* SPI transaction failed */ - break; - } - - *size = (header_slave[STATUS_HEADER_READY] == READY_NOW) ? - header_slave[size_offset] : 0; - attempts--; - } while ((*size == 0) && attempts); - - return ret; -} - -#elif DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) - -#define READ_CONDITION false -/* We cannot retry writing data without reading the header again */ -#define WRITE_DATA_CONDITION(...) true - -static void assert_cs(uint16_t delay) -{ - gpio_pin_set_dt(&bus.config.cs.gpio, 0); - if (delay) { - k_sleep(K_USEC(delay)); - } - gpio_pin_set_dt(&bus.config.cs.gpio, 1); - gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_DISABLE); -} - -static void release_cs(bool data_transaction) -{ - /* Consume possible event signals */ - while (k_sem_take(&sem_request, K_NO_WAIT) == 0) { - } - if (data_transaction) { - /* Wait for IRQ to become low only when data phase has been performed */ - while (IS_IRQ_HIGH) { - } - } - gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_TO_ACTIVE); - gpio_pin_set_dt(&bus.config.cs.gpio, 0); -} - -static int bt_spi_get_header(uint8_t op, uint16_t *size) -{ - uint8_t header_master[5] = {op, 0, 0, 0, 0}; - uint8_t header_slave[5]; - uint16_t cs_delay; - uint8_t size_offset; - int ret; - - if (op == SPI_READ) { - if (!IS_IRQ_HIGH) { - *size = 0; - return 0; - } - cs_delay = 0; - size_offset = STATUS_HEADER_TOREAD; - } else if (op == SPI_WRITE) { - /* To make sure we have a minimum delay from previous release cs */ - cs_delay = 100; - size_offset = STATUS_HEADER_TOWRITE; - } else { - return -EINVAL; - } - - assert_cs(cs_delay); - /* Wait up to a maximum time of 100 ms */ - if (!WAIT_FOR(IS_IRQ_HIGH, 100000, k_usleep(100))) { - LOG_ERR("IRQ pin did not raise"); - return -EIO; - } - - ret = bt_spi_transceive(header_master, 5, header_slave, 5); - *size = header_slave[size_offset] | (header_slave[size_offset + 1] << 8); - return ret; -} -/* Other Boards */ -#else - -#define release_cs(...) -#define READ_CONDITION false -#define WRITE_DATA_CONDITION(ret, rx_first) (rx_first != 0U || ret) - static int bt_spi_get_header(uint8_t op, uint16_t *size) { uint8_t header_master[5] = {op, 0, 0, 0, 0}; @@ -334,47 +180,6 @@ static int bt_spi_get_header(uint8_t op, uint16_t *size) return ret; } -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) */ - -#if defined(CONFIG_BT_BLUENRG_ACI) -static int bt_spi_send_aci_config(uint8_t offset, const uint8_t *value, size_t value_len) -{ - struct net_buf *buf; - uint8_t *cmd_data; - size_t data_len = 2 + value_len; - - buf = bt_hci_cmd_create(BLUENRG_ACI_WRITE_CONFIG_DATA, data_len); - if (!buf) { - return -ENOBUFS; - } - - cmd_data = net_buf_add(buf, data_len); - cmd_data[0] = offset; - cmd_data[1] = value_len; - memcpy(&cmd_data[2], value, value_len); - - return bt_hci_cmd_send(BLUENRG_ACI_WRITE_CONFIG_DATA, buf); -} - -static int bt_spi_bluenrg_setup(const struct bt_hci_setup_params *params) -{ - int ret; - const bt_addr_t *addr = ¶ms->public_addr; - - if (!bt_addr_eq(addr, BT_ADDR_NONE) && !bt_addr_eq(addr, BT_ADDR_ANY)) { - ret = bt_spi_send_aci_config( - BLUENRG_CONFIG_PUBADDR_OFFSET, - addr->val, sizeof(addr->val)); - - if (ret != 0) { - LOG_ERR("Failed to set BlueNRG public address (%d)", ret); - return ret; - } - } - - return 0; -} -#endif /* CONFIG_BT_BLUENRG_ACI */ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg) { @@ -453,48 +258,44 @@ static void bt_spi_rx_thread(void *p1, void *p2, void *p3) LOG_DBG(""); - do { - /* Wait for SPI bus to be available */ - k_sem_take(&sem_busy, K_FOREVER); - ret = bt_spi_get_header(SPI_READ, &size); - - /* Delay here is rounded up to next tick */ - k_sleep(K_USEC(DATA_DELAY_US)); - /* Read data */ - if (ret == 0 && size != 0) { - do { - ret = bt_spi_transceive(&txmsg, size, - &rxmsg, size); - if (rxmsg[0] == 0U) { - /* Consider increasing controller-data-delay-us - * if this message is extremely common. - */ - LOG_DBG("Controller not ready for SPI transaction " - "of %d bytes", size); - } - } while (rxmsg[0] == 0U && ret == 0); - } + /* Wait for SPI bus to be available */ + k_sem_take(&sem_busy, K_FOREVER); + ret = bt_spi_get_header(SPI_READ, &size); - release_cs(size > 0); + /* Delay here is rounded up to next tick */ + k_sleep(K_USEC(DATA_DELAY_US)); + /* Read data */ + if (ret == 0 && size != 0) { + do { + ret = bt_spi_transceive(&txmsg, size, + &rxmsg, size); + if (rxmsg[0] == 0U) { + /* Consider increasing controller-data-delay-us + * if this message is extremely common. + */ + LOG_DBG("Controller not ready for SPI transaction " + "of %d bytes", size); + } + } while (rxmsg[0] == 0U && ret == 0); + } - k_sem_give(&sem_busy); + k_sem_give(&sem_busy); - if (ret || size == 0) { - if (ret) { - LOG_ERR("Error %d", ret); - } - continue; + if (ret || size == 0) { + if (ret) { + LOG_ERR("Error %d", ret); } + continue; + } - LOG_HEXDUMP_DBG(rxmsg, size, "SPI RX"); + LOG_HEXDUMP_DBG(rxmsg, size, "SPI RX"); - /* Construct net_buf from SPI data */ - buf = bt_spi_rx_buf_construct(rxmsg); - if (buf) { - /* Handle the received HCI data */ - bt_recv(buf); - } - } while (READ_CONDITION); + /* Construct net_buf from SPI data */ + buf = bt_spi_rx_buf_construct(rxmsg); + if (buf) { + /* Handle the received HCI data */ + bt_recv(buf); + } } } @@ -544,7 +345,7 @@ static int bt_spi_send(struct net_buf *buf) while (true) { ret = bt_spi_transceive(buf->data, size, rx_first, 1); - if (WRITE_DATA_CONDITION(ret, rx_first[0])) { + if (rx_first[0] != 0U || ret) { break; } /* Consider increasing controller-data-delay-us @@ -554,8 +355,6 @@ static int bt_spi_send(struct net_buf *buf) } } - release_cs(size > 0); - k_sem_give(&sem_busy); if (ret) { @@ -565,18 +364,6 @@ static int bt_spi_send(struct net_buf *buf) LOG_HEXDUMP_DBG(buf->data, buf->len, "SPI TX"); -#if (DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) || DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2)) - /* - * Since a RESET has been requested, the chip will now restart. - * Unfortunately the BlueNRG will reply with "reset received" but - * since it does not send back a NOP, we have no way to tell when the - * RESET has actually taken place. Instead, we use the vendor command - * EVT_BLUE_INITIALIZED as an indication that it is safe to proceed. - */ - if (bt_spi_get_cmd(buf->data) == BT_HCI_OP_RESET) { - k_sem_take(&sem_initialised, K_FOREVER); - } -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) || DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) */ out: net_buf_unref(buf); @@ -631,10 +418,6 @@ static int bt_spi_open(void) static const struct bt_hci_driver drv = { .name = DEVICE_DT_NAME(DT_DRV_INST(0)), .bus = BT_HCI_DRIVER_BUS_SPI, -#if defined(CONFIG_BT_BLUENRG_ACI) - .quirks = BT_QUIRK_NO_RESET, - .setup = bt_spi_bluenrg_setup, -#endif /* CONFIG_BT_BLUENRG_ACI */ .open = bt_spi_open, .send = bt_spi_send, }; diff --git a/drivers/can/Kconfig.mcux b/drivers/can/Kconfig.mcux index 5983be36c8ae0e6..7df67684e8a7c7b 100644 --- a/drivers/can/Kconfig.mcux +++ b/drivers/can/Kconfig.mcux @@ -31,8 +31,10 @@ config CAN_MCUX_FLEXCAN_WAIT_TIMEOUT config CAN_MAX_MB int "Maximum number of message buffers for concurrent active instances" default 16 - depends on SOC_SERIES_S32K3XX - range 1 96 + depends on SOC_SERIES_S32K3XX || SOC_SERIES_S32K1XX + range 1 96 if SOC_SERIES_S32K3XX + range 1 32 if SOC_SERIES_S32K1XX && !SOC_S32K142W && !SOC_S32K144W + range 1 64 if SOC_S32K142W || SOC_S32K144W help Defines maximum number of message buffers for concurrent active instances. @@ -43,6 +45,8 @@ config CAN_MAX_FILTER range 1 13 if SOC_SERIES_IMX_RT && CAN_MCUX_FLEXCAN_FD range 1 63 if SOC_SERIES_IMX_RT range 1 96 if SOC_SERIES_S32K3XX + range 1 32 if SOC_SERIES_S32K1XX && !SOC_S32K142W && !SOC_S32K144W + range 1 64 if SOC_S32K142W || SOC_S32K144W help Defines maximum number of concurrent active RX filters diff --git a/drivers/can/can_mcux_mcan.c b/drivers/can/can_mcux_mcan.c index eb382c952929d78..b4c24e2b19eec71 100644 --- a/drivers/can/can_mcux_mcan.c +++ b/drivers/can/can_mcux_mcan.c @@ -217,17 +217,17 @@ static const struct can_mcan_ops mcux_mcan_ops = { \ static void mcux_mcan_irq_config_##n(const struct device *dev) \ { \ - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 0, irq), \ - DT_INST_IRQ_BY_IDX(n, 0, priority), \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, int0, irq), \ + DT_INST_IRQ_BY_NAME(n, int0, priority), \ can_mcan_line_0_isr, \ DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQ_BY_IDX(n, 0, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, int0, irq)); \ \ - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 1, irq), \ - DT_INST_IRQ_BY_IDX(n, 1, priority), \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, int1, irq), \ + DT_INST_IRQ_BY_NAME(n, int1, priority), \ can_mcan_line_1_isr, \ DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQ_BY_IDX(n, 1, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, int1, irq)); \ } DT_INST_FOREACH_STATUS_OKAY(MCUX_MCAN_INIT) diff --git a/drivers/can/can_numaker.c b/drivers/can/can_numaker.c index 0bb47d78a045469..c2e7bba39434cac 100644 --- a/drivers/can/can_numaker.c +++ b/drivers/can/can_numaker.c @@ -249,18 +249,18 @@ static const struct can_mcan_ops can_numaker_ops = { \ static void can_numaker_irq_config_func_##inst(const struct device *dev) \ { \ - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(inst, 0, irq), \ - DT_INST_IRQ_BY_IDX(inst, 0, priority), \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, int0, irq), \ + DT_INST_IRQ_BY_NAME(inst, int0, priority), \ can_mcan_line_0_isr, \ DEVICE_DT_INST_GET(inst), \ 0); \ - irq_enable(DT_INST_IRQ_BY_IDX(inst, 0, irq)); \ - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(inst, 1, irq), \ - DT_INST_IRQ_BY_IDX(inst, 1, priority), \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, int0, irq)); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, int1, irq), \ + DT_INST_IRQ_BY_NAME(inst, int1, priority), \ can_mcan_line_1_isr, \ DEVICE_DT_INST_GET(inst), \ 0); \ - irq_enable(DT_INST_IRQ_BY_IDX(inst, 1, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, int1, irq)); \ } \ \ static const struct can_numaker_config can_numaker_config_##inst = { \ @@ -288,7 +288,7 @@ static const struct can_mcan_ops can_numaker_ops = { CAN_MCAN_DATA_INITIALIZER(&can_numaker_data_ ## inst); \ \ CAN_DEVICE_DT_INST_DEFINE(inst, \ - &can_numaker_init, \ + can_numaker_init, \ NULL, \ &can_mcan_data_##inst, \ &can_mcan_config_##inst, \ diff --git a/drivers/can/can_sam.c b/drivers/can/can_sam.c index e081e57c7947326..4be722386ae0083 100644 --- a/drivers/can/can_sam.c +++ b/drivers/can/can_sam.c @@ -154,14 +154,14 @@ static const struct can_mcan_ops can_sam_ops = { static void config_can_##inst##_irq(void) \ { \ LOG_DBG("Enable CAN##inst## IRQ"); \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, line_0, irq), \ - DT_INST_IRQ_BY_NAME(inst, line_0, priority), can_mcan_line_0_isr, \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, int0, irq), \ + DT_INST_IRQ_BY_NAME(inst, int0, priority), can_mcan_line_0_isr, \ DEVICE_DT_INST_GET(inst), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(inst, line_0, irq)); \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, line_1, irq), \ - DT_INST_IRQ_BY_NAME(inst, line_1, priority), can_mcan_line_1_isr, \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, int0, irq)); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, int1, irq), \ + DT_INST_IRQ_BY_NAME(inst, int1, priority), can_mcan_line_1_isr, \ DEVICE_DT_INST_GET(inst), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(inst, line_1, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, int1, irq)); \ } #define CAN_SAM_CFG_INST(inst) \ diff --git a/drivers/can/can_sam0.c b/drivers/can/can_sam0.c index 05465de13c1edff..af584df619af801 100644 --- a/drivers/can/can_sam0.c +++ b/drivers/can/can_sam0.c @@ -199,10 +199,10 @@ static const struct can_mcan_ops can_sam0_ops = { static void config_can_##inst##_irq(void) \ { \ LOG_DBG("Enable CAN##inst## IRQ"); \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, line_0, irq), \ - DT_INST_IRQ_BY_NAME(inst, line_0, priority), can_sam0_line_x_isr, \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, int0, irq), \ + DT_INST_IRQ_BY_NAME(inst, int0, priority), can_sam0_line_x_isr, \ DEVICE_DT_INST_GET(inst), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(inst, line_0, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, int0, irq)); \ } #define CAN_SAM0_CFG_INST(inst) \ diff --git a/drivers/can/can_stm32_fdcan.c b/drivers/can/can_stm32_fdcan.c index e17fce0e1b96e8f..1237ddad7b31533 100644 --- a/drivers/can/can_stm32_fdcan.c +++ b/drivers/can/can_stm32_fdcan.c @@ -630,14 +630,14 @@ static const struct can_mcan_ops can_stm32fd_ops = { static void config_can_##inst##_irq(void) \ { \ LOG_DBG("Enable CAN" #inst " IRQ"); \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, line_0, irq), \ - DT_INST_IRQ_BY_NAME(inst, line_0, priority), \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, int0, irq), \ + DT_INST_IRQ_BY_NAME(inst, int0, priority), \ can_mcan_line_0_isr, DEVICE_DT_INST_GET(inst), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(inst, line_0, irq)); \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, line_1, irq), \ - DT_INST_IRQ_BY_NAME(inst, line_1, priority), \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, int0, irq)); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, int1, irq), \ + DT_INST_IRQ_BY_NAME(inst, int1, priority), \ can_mcan_line_1_isr, DEVICE_DT_INST_GET(inst), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(inst, line_1, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, int1, irq)); \ } #define CAN_STM32FD_CFG_INST(inst) \ diff --git a/drivers/can/can_stm32h7_fdcan.c b/drivers/can/can_stm32h7_fdcan.c index 291bcfe80916a4f..9b75932fd4f8d5f 100644 --- a/drivers/can/can_stm32h7_fdcan.c +++ b/drivers/can/can_stm32h7_fdcan.c @@ -233,14 +233,14 @@ static const struct can_mcan_ops can_stm32h7_ops = { static void stm32h7_mcan_irq_config_##n(void) \ { \ LOG_DBG("Enable CAN inst" #n " IRQ"); \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, line_0, irq), \ - DT_INST_IRQ_BY_NAME(n, line_0, priority), \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, int0, irq), \ + DT_INST_IRQ_BY_NAME(n, int0, priority), \ can_mcan_line_0_isr, DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(n, line_0, irq)); \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, line_1, irq), \ - DT_INST_IRQ_BY_NAME(n, line_1, priority), \ + irq_enable(DT_INST_IRQ_BY_NAME(n, int0, irq)); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, int1, irq), \ + DT_INST_IRQ_BY_NAME(n, int1, priority), \ can_mcan_line_1_isr, DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(n, line_1, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, int1, irq)); \ } DT_INST_FOREACH_STATUS_OKAY(CAN_STM32H7_MCAN_INIT) diff --git a/drivers/charger/CMakeLists.txt b/drivers/charger/CMakeLists.txt index ce70f0590c601bf..60b80b0ed25cd4f 100644 --- a/drivers/charger/CMakeLists.txt +++ b/drivers/charger/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_library() zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/charger.h) zephyr_library_sources_ifdef(CONFIG_CHARGER_BQ24190 charger_bq24190.c) +zephyr_library_sources_ifdef(CONFIG_CHARGER_BQ25180 charger_bq25180.c) zephyr_library_sources_ifdef(CONFIG_CHARGER_MAX20335 charger_max20335.c) zephyr_library_sources_ifdef(CONFIG_SBS_CHARGER sbs_charger.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE charger_handlers.c) diff --git a/drivers/charger/Kconfig b/drivers/charger/Kconfig index 9c7873168a5c9e9..ce2c3d8b8d39c4f 100644 --- a/drivers/charger/Kconfig +++ b/drivers/charger/Kconfig @@ -21,6 +21,7 @@ config CHARGER_INIT_PRIORITY source "drivers/charger/Kconfig.sbs_charger" source "drivers/charger/Kconfig.bq24190" +source "drivers/charger/Kconfig.bq25180" source "drivers/charger/Kconfig.max20335" endif # CHARGER diff --git a/drivers/charger/Kconfig.bq25180 b/drivers/charger/Kconfig.bq25180 new file mode 100644 index 000000000000000..44bdc9b32ee495c --- /dev/null +++ b/drivers/charger/Kconfig.bq25180 @@ -0,0 +1,11 @@ +# Copyright 2024 Google LLC +# +# SPDX-License-Identifier: Apache-2.0 + +config CHARGER_BQ25180 + bool "BQ25180 Battery Charger" + default y + depends on DT_HAS_TI_BQ25180_ENABLED + select I2C + help + Enable BQ25180 battery charger driver. diff --git a/drivers/charger/charger_bq25180.c b/drivers/charger/charger_bq25180.c new file mode 100644 index 000000000000000..7063377c5893b4f --- /dev/null +++ b/drivers/charger/charger_bq25180.c @@ -0,0 +1,218 @@ +/* + * Copyright 2024 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + * + * BQ25180 Datasheet: https://www.ti.com/lit/gpn/bq25180 + */ + +#define DT_DRV_COMPAT ti_bq25180 + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(bq25180, CONFIG_CHARGER_LOG_LEVEL); + +#define BQ25180_STAT0 0x00 +#define BQ25180_STAT1 0x01 +#define BQ25180_FLAG0 0x02 +#define BQ25180_VBAT_CTRL 0x03 +#define BQ25180_ICHG_CTRL 0x04 +#define BQ25180_IC_CTRL 0x07 +#define BQ25180_SHIP_RST 0x09 +#define BQ25180_MASK_ID 0x0c + +#define BQ25180_ICHG_CHG_DIS BIT(7) +#define BQ25180_ICHG_MSK GENMASK(6, 0) +#define BQ25180_WATCHDOG_SEL_1_MSK GENMASK(1, 0) +#define BQ25180_WATCHDOG_DISABLE 0x03 +#define BQ25180_DEVICE_ID_MSK GENMASK(3, 0) +#define BQ25180_DEVICE_ID 0x00 +#define BQ25180_SHIP_RST_EN_RST_SHIP_MSK GENMASK(6, 5) +#define BQ25180_SHIP_RST_EN_RST_SHIP_ADAPTER 0x20 +#define BQ25180_SHIP_RST_EN_RST_SHIP_BUTTON 0x40 + +/* Charging current limits */ +#define BQ25180_CURRENT_MIN_MA 5 +#define BQ25180_CURRENT_MAX_MA 1000 + +struct bq25180_config { + struct i2c_dt_spec i2c; + uint32_t initial_current_microamp; +}; + +/* + * For ICHG <= 35mA = ICHGCODE + 5mA + * For ICHG > 35mA = 40 + ((ICHGCODE-31)*10)mA. + * Maximum programmable current = 1000mA + * + * Return: value between 0 and 127, negative on error. + */ +static int bq25180_ma_to_ichg(uint32_t current_ma, uint8_t *ichg) +{ + if (!IN_RANGE(current_ma, BQ25180_CURRENT_MIN_MA, BQ25180_CURRENT_MAX_MA)) { + LOG_WRN("charging current out of range: %dmA, " + "clamping to the nearest limit", current_ma); + } + current_ma = CLAMP(current_ma, BQ25180_CURRENT_MIN_MA, BQ25180_CURRENT_MAX_MA); + + if (current_ma <= 35) { + *ichg = current_ma - 5; + return 0; + } + + *ichg = (current_ma - 40) / 10 + 31; + + return 0; +} + +static uint32_t bq25180_ichg_to_ma(uint8_t ichg) +{ + ichg &= BQ25180_ICHG_MSK; + + if (ichg <= 30) { + return (ichg + 5); + } + + return (ichg - 31) * 10 + 40; +} + +static int bq25183_charge_enable(const struct device *dev, const bool enable) +{ + const struct bq25180_config *cfg = dev->config; + uint8_t value = enable ? 0 : BQ25180_ICHG_CHG_DIS; + int ret; + + ret = i2c_reg_update_byte_dt(&cfg->i2c, BQ25180_ICHG_CTRL, + BQ25180_ICHG_CHG_DIS, value); + if (ret < 0) { + return ret; + } + + return 0; +} + +static int bq25180_set_charge_current(const struct device *dev, + uint32_t const_charge_current_ua) +{ + const struct bq25180_config *cfg = dev->config; + uint8_t val; + int ret; + + ret = bq25180_ma_to_ichg(const_charge_current_ua / 1000, &val); + if (ret < 0) { + return ret; + } + + ret = i2c_reg_update_byte_dt(&cfg->i2c, BQ25180_ICHG_CTRL, + BQ25180_ICHG_MSK, val); + if (ret < 0) { + return ret; + } + + return 0; +} + +static int bq25180_get_charge_current(const struct device *dev, + uint32_t *const_charge_current_ua) +{ + const struct bq25180_config *cfg = dev->config; + uint8_t val; + int ret; + + ret = i2c_reg_read_byte_dt(&cfg->i2c, BQ25180_ICHG_CTRL, &val); + if (ret < 0) { + return ret; + } + + *const_charge_current_ua = bq25180_ichg_to_ma(val) * 1000; + + return 0; +} + +static int bq25180_get_prop(const struct device *dev, charger_prop_t prop, + union charger_propval *val) +{ + switch (prop) { + case CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA: + return bq25180_get_charge_current(dev, &val->const_charge_current_ua); + default: + return -ENOTSUP; + } +} + +static int bq25180_set_prop(const struct device *dev, charger_prop_t prop, + const union charger_propval *val) +{ + switch (prop) { + case CHARGER_PROP_CONSTANT_CHARGE_CURRENT_UA: + return bq25180_set_charge_current(dev, val->const_charge_current_ua); + default: + return -ENOTSUP; + } +} + +static const struct charger_driver_api bq25180_api = { + .get_property = bq25180_get_prop, + .set_property = bq25180_set_prop, + .charge_enable = bq25183_charge_enable, +}; + +static int bq25180_init(const struct device *dev) +{ + const struct bq25180_config *cfg = dev->config; + uint8_t val; + int ret; + + ret = i2c_reg_read_byte_dt(&cfg->i2c, BQ25180_MASK_ID, &val); + if (ret < 0) { + return ret; + } + + val &= BQ25180_DEVICE_ID_MSK; + if (val != BQ25180_DEVICE_ID) { + LOG_ERR("Invalid device id: %02x", val); + return -EINVAL; + } + + /* Disable the watchdog */ + ret = i2c_reg_update_byte_dt(&cfg->i2c, BQ25180_IC_CTRL, + BQ25180_WATCHDOG_SEL_1_MSK, + BQ25180_WATCHDOG_DISABLE); + if (ret < 0) { + return ret; + } + + if (cfg->initial_current_microamp > 0) { + ret = bq25180_ma_to_ichg(cfg->initial_current_microamp / 1000, &val); + if (ret < 0) { + return ret; + } + + ret = i2c_reg_update_byte_dt(&cfg->i2c, BQ25180_ICHG_CTRL, + BQ25180_ICHG_MSK, val); + if (ret < 0) { + return ret; + } + } + + return 0; +} + +#define CHARGER_BQ25180_INIT(inst) \ + static const struct bq25180_config bq25180_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + .initial_current_microamp = DT_INST_PROP( \ + inst, constant_charge_current_max_microamp), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, bq25180_init, NULL, NULL, \ + &bq25180_config_##inst, POST_KERNEL, \ + CONFIG_CHARGER_INIT_PRIORITY, \ + &bq25180_api); + +DT_INST_FOREACH_STATUS_OKAY(CHARGER_BQ25180_INIT) diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index 23856ff7e2dfe48..9d76004c92fdf45 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -824,14 +824,13 @@ static int set_up_plls(void) return 0; } -#if defined(CONFIG_CPU_CORTEX_M7) int stm32_clock_control_init(const struct device *dev) { + int r = 0; + +#if defined(CONFIG_CPU_CORTEX_M7) uint32_t old_hclk_freq = 0; uint32_t new_hclk_freq = 0; - int r; - - ARG_UNUSED(dev); /* HW semaphore Clock enable */ #if defined(CONFIG_SOC_STM32H7A3XX) || defined(CONFIG_SOC_STM32H7A3XXQ) || \ @@ -917,23 +916,15 @@ int stm32_clock_control_init(const struct device *dev) optimize_regulator_voltage_scale(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); +#endif /* CONFIG_CPU_CORTEX_M7 */ - /* Update CMSIS variable */ - SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; - - return r; -} -#else -int stm32_clock_control_init(const struct device *dev) -{ ARG_UNUSED(dev); /* Update CMSIS variable */ SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; - return 0; + return r; } -#endif /* CONFIG_CPU_CORTEX_M7 */ #if defined(STM32_HSE_CSS) void __weak stm32_hse_css_callback(void) {} diff --git a/drivers/clock_control/clock_stm32f2_f4_f7.c b/drivers/clock_control/clock_stm32f2_f4_f7.c index 6131fcd4c0672e7..a10fede688704b1 100644 --- a/drivers/clock_control/clock_stm32f2_f4_f7.c +++ b/drivers/clock_control/clock_stm32f2_f4_f7.c @@ -56,6 +56,9 @@ uint32_t get_pllsrc_frequency(void) __unused void config_pll_sysclock(void) { +#if defined(STM32_SRC_PLL_R) && STM32_PLL_R_ENABLED && defined(RCC_PLLCFGR_PLLR) + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLR, pllr(STM32_PLL_R_DIVISOR)); +#endif LL_RCC_PLL_ConfigDomain_SYS(get_pll_source(), pllm(STM32_PLL_M_DIVISOR), STM32_PLL_N_MULTIPLIER, diff --git a/drivers/counter/Kconfig.gd32 b/drivers/counter/Kconfig.gd32 index eb5d5897af26c1d..fcb8913434e4d6c 100644 --- a/drivers/counter/Kconfig.gd32 +++ b/drivers/counter/Kconfig.gd32 @@ -6,7 +6,7 @@ config COUNTER_TIMER_GD32 bool "GD32 timer counter driver" default y - depends on DT_HAS_GD_GD32_TIMER_ENABLED && SOC_FAMILY_GD32_ARM + depends on DT_HAS_GD_GD32_TIMER_ENABLED && !SOC_SERIES_GD32VF103 select USE_GD32_TIMER help Enable counter timer driver for GD32 series devices. diff --git a/drivers/counter/counter_ambiq_timer.c b/drivers/counter/counter_ambiq_timer.c index 94549d6568576c4..67df6c5647f6906 100644 --- a/drivers/counter/counter_ambiq_timer.c +++ b/drivers/counter/counter_ambiq_timer.c @@ -43,7 +43,6 @@ static int counter_ambiq_init(const struct device *dev) tc.ui32PatternLimit = 0; am_hal_timer_config(0, &tc); - am_hal_timer_interrupt_enable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); k_spin_unlock(&lock, key); @@ -98,6 +97,10 @@ static int counter_ambiq_set_alarm(const struct device *dev, uint8_t chan_id, k_spinlock_key_t key = k_spin_lock(&lock); + /* Enable interrupt, due to counter_ambiq_cancel_alarm() disables it*/ + am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + am_hal_timer_interrupt_enable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { am_hal_timer_compare1_set(0, now + alarm_cfg->ticks); } else { @@ -119,6 +122,8 @@ static int counter_ambiq_cancel_alarm(const struct device *dev, uint8_t chan_id) k_spinlock_key_t key = k_spin_lock(&lock); am_hal_timer_interrupt_disable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + /* Reset the compare register */ + am_hal_timer_compare1_set(0, 0); k_spin_unlock(&lock, key); return 0; diff --git a/drivers/counter/counter_nrfx_timer.c b/drivers/counter/counter_nrfx_timer.c index caf2c5852e4d6d1..47537b16d7d44a7 100644 --- a/drivers/counter/counter_nrfx_timer.c +++ b/drivers/counter/counter_nrfx_timer.c @@ -364,8 +364,10 @@ static void alarm_irq_handle(const struct device *dev, uint32_t id) } } -static void irq_handler(const struct device *dev) +static void irq_handler(const void *arg) { + const struct device *dev = arg; + top_irq_handle(dev); for (uint32_t i = 0; i < counter_get_num_of_channels(dev); i++) { @@ -437,7 +439,7 @@ static const struct counter_driver_api counter_nrfx_driver_api = { .channels = CC_TO_ID(DT_INST_PROP(idx, cc_num)), \ }, \ .ch_data = counter##idx##_ch_data, \ - .timer = (NRF_TIMER_Type *)DT_INST_REG_ADDR(idx), \ + .timer = (NRF_TIMER_Type *)_CONCAT(NRF_TIMER, idx), \ LOG_INSTANCE_PTR_INIT(log, LOG_MODULE_NAME, idx) \ }; \ DEVICE_DT_INST_DEFINE(idx, \ diff --git a/drivers/display/display_nrf_led_matrix.c b/drivers/display/display_nrf_led_matrix.c index 5468347551da6da..d88bc760e76adc7 100644 --- a/drivers/display/display_nrf_led_matrix.c +++ b/drivers/display/display_nrf_led_matrix.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #ifdef PWM_PRESENT #include @@ -89,6 +90,8 @@ struct display_drv_config { NRF_TIMER_Type *timer; #if USE_PWM NRF_PWM_Type *pwm; +#else + nrfx_gpiote_t gpiote; #endif uint8_t rows[ROW_COUNT]; uint8_t cols[COL_COUNT]; @@ -324,7 +327,7 @@ static void prepare_pixel_pulse(const struct device *dev, /* First timer channel is used for timing the period of pulses. */ nrf_timer_cc_set(dev_config->timer, 1 + channel_idx, pulse); - NRF_GPIOTE->CONFIG[dev_data->gpiote_ch[channel_idx]] = gpiote_cfg; + dev_config->gpiote.p_reg->CONFIG[dev_data->gpiote_ch[channel_idx]] = gpiote_cfg; #endif /* USE_PWM */ } @@ -354,7 +357,7 @@ static void timer_irq_handler(void *arg) } #else for (int i = 0; i < GROUP_SIZE; ++i) { - NRF_GPIOTE->CONFIG[dev_data->gpiote_ch[i]] = 0; + dev_config->gpiote.p_reg->CONFIG[dev_data->gpiote_ch[i]] = 0; } #endif @@ -450,7 +453,7 @@ static int instance_init(const struct device *dev) return -ENOMEM; } - err = nrfx_gpiote_channel_alloc(gpiote_ch); + err = nrfx_gpiote_channel_alloc(&dev_config->gpiote, gpiote_ch); if (err != NRFX_SUCCESS) { LOG_ERR("Failed to allocate GPIOTE channel."); /* Do not bother with freeing resources allocated @@ -463,7 +466,7 @@ static int instance_init(const struct device *dev) nrf_ppi_channel_endpoint_setup(NRF_PPI, ppi_ch, nrf_timer_event_address_get(dev_config->timer, nrf_timer_compare_event_get(1 + i)), - nrf_gpiote_event_address_get(NRF_GPIOTE, + nrf_gpiote_event_address_get(dev_config->gpiote.p_reg, nrf_gpiote_out_task_get(*gpiote_ch))); nrf_ppi_channel_enable(NRF_PPI, ppi_ch); } @@ -514,6 +517,14 @@ static struct display_drv_data instance_data = { .blanking = true, }; +#if !USE_PWM +#define CHECK_GPIOTE_INST(node_id, prop, idx) \ + BUILD_ASSERT(NRF_DT_GPIOTE_INST_BY_IDX(node_id, prop, idx) == \ + NRF_DT_GPIOTE_INST_BY_IDX(node_id, prop, 0), \ + "All column GPIOs must use the same GPIOTE instance"); +DT_FOREACH_PROP_ELEM(MATRIX_NODE, col_gpios, CHECK_GPIOTE_INST) +#endif + #define GET_PIN_INFO(node_id, pha, idx) \ (DT_GPIO_PIN_BY_IDX(node_id, pha, idx) | \ (DT_PROP_BY_PHANDLE_IDX(node_id, pha, idx, port) << 5) | \ @@ -530,6 +541,9 @@ static const struct display_drv_config instance_config = { .timer = (NRF_TIMER_Type *)DT_REG_ADDR(TIMER_NODE), #if USE_PWM .pwm = (NRF_PWM_Type *)DT_REG_ADDR(PWM_NODE), +#else + .gpiote = NRFX_GPIOTE_INSTANCE( + NRF_DT_GPIOTE_INST_BY_IDX(MATRIX_NODE, col_gpios, 0)), #endif .rows = { DT_FOREACH_PROP_ELEM(MATRIX_NODE, row_gpios, GET_PIN_INFO) }, .cols = { DT_FOREACH_PROP_ELEM(MATRIX_NODE, col_gpios, GET_PIN_INFO) }, diff --git a/drivers/display/display_sdl_bottom.c b/drivers/display/display_sdl_bottom.c index 92c09f36fcd9b64..bfeb70a8dba93fc 100644 --- a/drivers/display/display_sdl_bottom.c +++ b/drivers/display/display_sdl_bottom.c @@ -29,6 +29,8 @@ int sdl_display_init_bottom(uint16_t height, uint16_t width, uint16_t zoom_pct, return -1; } + SDL_RenderSetLogicalSize(*renderer, width, height); + *texture = SDL_CreateTexture(*renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height); if (*texture == NULL) { diff --git a/drivers/ethernet/CMakeLists.txt b/drivers/ethernet/CMakeLists.txt index 7b925b3730aa1e1..def0c5bf186e7f8 100644 --- a/drivers/ethernet/CMakeLists.txt +++ b/drivers/ethernet/CMakeLists.txt @@ -36,6 +36,7 @@ zephyr_library_sources_ifdef(CONFIG_ETH_IVSHMEM eth_ivshmem.c eth_ivshmem_queue zephyr_library_sources_ifdef(CONFIG_ETH_ADIN2111 eth_adin2111.c) zephyr_library_sources_ifdef(CONFIG_ETH_LAN865X eth_lan865x.c oa_tc6.c) zephyr_library_sources_ifdef(CONFIG_ETH_NXP_ENET eth_nxp_enet.c) +zephyr_library_sources_ifdef(CONFIG_ETH_XMC4XXX eth_xmc4xxx.c) if(CONFIG_ETH_NXP_S32_NETC) zephyr_library_sources(eth_nxp_s32_netc.c) diff --git a/drivers/ethernet/Kconfig b/drivers/ethernet/Kconfig index e26c0bafb6d5623..4bc7b8b9599860a 100644 --- a/drivers/ethernet/Kconfig +++ b/drivers/ethernet/Kconfig @@ -64,6 +64,7 @@ source "drivers/ethernet/Kconfig.adin2111" source "drivers/ethernet/Kconfig.numaker" source "drivers/ethernet/Kconfig.lan865x" source "drivers/ethernet/Kconfig.nxp_enet" +source "drivers/ethernet/Kconfig.xmc4xxx" source "drivers/ethernet/phy/Kconfig" diff --git a/drivers/ethernet/Kconfig.stm32_hal b/drivers/ethernet/Kconfig.stm32_hal index 4f5f79d1f636a45..8161ea31f5f9d59 100644 --- a/drivers/ethernet/Kconfig.stm32_hal +++ b/drivers/ethernet/Kconfig.stm32_hal @@ -137,7 +137,7 @@ config ETH_STM32_AUTO_NEGOTIATION_ENABLE config ETH_STM32_HW_CHECKSUM bool "Use TX and RX hardware checksum" - depends on (!SOC_SERIES_STM32H7X && !SOC_SERIES_STM32H5X ) + depends on !SOC_SERIES_STM32H5X help Enable receive and transmit checksum offload to enhance throughput performances. diff --git a/drivers/ethernet/Kconfig.xmc4xxx b/drivers/ethernet/Kconfig.xmc4xxx new file mode 100644 index 000000000000000..258d1462b8f2c63 --- /dev/null +++ b/drivers/ethernet/Kconfig.xmc4xxx @@ -0,0 +1,56 @@ +# ETH_XMC4XXX Ethernet driver configuration options + +# Copyright (c) 2023 SLB +# SPDX-License-Identifier: Apache-2.0 + +menuconfig ETH_XMC4XXX + bool "XMC4XXX Ethernet driver" + default y + depends on DT_HAS_INFINEON_XMC4XXX_ETHERNET_ENABLED + help + Enable XMC4XXX Ethernet driver. + +if ETH_XMC4XXX + +config ETH_XMC4XXX_TX_FRAME_POOL_SIZE + int "Number of TX frames in the pool size" + default 4 + help + Number of TX frames which can be buffered in the driver. + +config ETH_XMC4XXX_NUM_TX_DMA_DESCRIPTORS + int "Number of TX DMA descriptors" + default 32 + help + Number of TX DMA descriptors. Each descriptor stores the memory address of a + data fragment and its size. + +config ETH_XMC4XXX_NUM_RX_DMA_DESCRIPTORS + int "Number of RX DMA descriptors" + default 12 + help + Number of RX DMA descriptors. Each descriptor stores the memory address of a + data fragment and its size. The data fragments are pre-allocated from the rx + network buffers (CONFIG_NET_BUF_RX_COUNT). When a frame is received, it is + forwarded to the network stack without copying the data. The buffers + in the descriptors are replaced by new pre-allocated buffers. + +config ETH_XMC4XXX_VLAN_HW_FILTER + bool "Hardware filter VLAN frames" + default y if NET_VLAN_COUNT=1 + depends on NET_VLAN + help + Hardware filter VLAN frames in hardware. Only ethernet frames with + a tag configured using vlan_setup() call will be received. + The filtering can only be done on one vlan tag. If vlan_setup() is + called multiple times, the filtering will be done on the latest + tag. + +config PTP_CLOCK_XMC4XXX + bool "XMC4XXX PTP clock driver support" + default y + depends on PTP_CLOCK + help + Enable XMC4XXX PTP Clock support. + +endif # ETH_XMC4XXX diff --git a/drivers/ethernet/eth_xmc4xxx.c b/drivers/ethernet/eth_xmc4xxx.c new file mode 100644 index 000000000000000..ad2cee470f2d3d8 --- /dev/null +++ b/drivers/ethernet/eth_xmc4xxx.c @@ -0,0 +1,1162 @@ +/* XMC4XXX Ethernet controller + * + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT infineon_xmc4xxx_ethernet + +#include "eth.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL +#include +LOG_MODULE_REGISTER(eth_xmc4xxx); + +#define NUM_TX_DMA_DESCRIPTORS CONFIG_ETH_XMC4XXX_NUM_TX_DMA_DESCRIPTORS +#define NUM_RX_DMA_DESCRIPTORS CONFIG_ETH_XMC4XXX_NUM_RX_DMA_DESCRIPTORS + +#define ETH_NODE DT_NODELABEL(eth) +#define PHY_NODE DT_PHANDLE_BY_IDX(ETH_NODE, phy, 0) + +#define INFINEON_OUI_B0 0x00 +#define INFINEON_OUI_B1 0x03 +#define INFINEON_OUI_B2 0x19 + +#define MODULO_INC_TX(val) {(val) = (++(val) < NUM_TX_DMA_DESCRIPTORS) ? (val) : 0; } +#define MODULO_INC_RX(val) {(val) = (++(val) < NUM_RX_DMA_DESCRIPTORS) ? (val) : 0; } + +#define IS_OWNED_BY_DMA_TX(desc) (((desc)->status & ETH_MAC_DMA_TDES0_OWN) != 0) +#define IS_OWNED_BY_DMA_RX(desc) (((desc)->status & ETH_MAC_DMA_RDES0_OWN) != 0) + +#define IS_START_OF_FRAME_RX(desc) (((desc)->status & ETH_MAC_DMA_RDES0_FS) != 0) +#define IS_END_OF_FRAME_RX(desc) (((desc)->status & ETH_MAC_DMA_RDES0_LS) != 0) + +#define IS_TIMESTAMP_AVAILABLE_RX(desc) (((desc)->status & ETH_MAC_DMA_RDES0_TSA) != 0) +#define IS_TIMESTAMP_AVAILABLE_TX(desc) (((desc)->status & ETH_MAC_DMA_TDES0_TTSS) != 0) + +#define TOTAL_FRAME_LENGTH(desc) (FIELD_GET(ETH_MAC_DMA_RDES0_FL, (desc)->status) - 4) + +#define ETH_STATUS_ERROR_TRANSMIT_EVENTS \ + (XMC_ETH_MAC_EVENT_BUS_ERROR | XMC_ETH_MAC_EVENT_TRANSMIT_JABBER_TIMEOUT | \ + XMC_ETH_MAC_EVENT_TRANSMIT_UNDERFLOW | XMC_ETH_MAC_EVENT_TRANSMIT_PROCESS_STOPPED) + +#define ETH_STATUS_ERROR_RECEIVE_EVENTS \ + (XMC_ETH_MAC_EVENT_BUS_ERROR | XMC_ETH_MAC_EVENT_RECEIVE_OVERFLOW) + +#define ETH_STATUS_ALL_EVENTS \ + (ETH_STATUS_ERROR_TRANSMIT_EVENTS | ETH_STATUS_ERROR_RECEIVE_EVENTS | \ + XMC_ETH_MAC_EVENT_RECEIVE | XMC_ETH_MAC_EVENT_TRANSMIT | ETH_INTERRUPT_ENABLE_NIE_Msk | \ + ETH_INTERRUPT_ENABLE_AIE_Msk) + +#define ETH_MAC_DISABLE_MMC_INTERRUPT_MSK 0x03ffffffu +#define ETH_MAC_DISABLE_MMC_IPC_RECEIVE_INTERRUPT_MSK 0x3fff3fffu + +#define ETH_STATUS_CLEARABLE_BITS 0x1e7ffu + +#define ETH_RX_DMA_DESC_SECOND_ADDR_CHAINED_MASK BIT(14) + +#define ETH_RESET_TIMEOUT_USEC 200000u +#define ETH_TIMESTAMP_CONTROL_REG_TIMEOUT_USEC 100000u + +#define ETH_LINK_SPEED_10M 0 +#define ETH_LINK_SPEED_100M 1 + +#define ETH_LINK_DUPLEX_HALF 0 +#define ETH_LINK_DUPLEX_FULL 1 + +#define ETH_PTP_CLOCK_FREQUENCY 50000000 +#define ETH_PTP_RATE_ADJUST_RATIO_MIN 0.9 +#define ETH_PTP_RATE_ADJUST_RATIO_MAX 1.1 + +struct eth_xmc4xxx_data { + struct net_if *iface; + uint8_t mac_addr[6]; + struct k_sem tx_desc_sem; + bool link_up; +#if defined(CONFIG_NET_STATISTICS_ETHERNET) + struct net_stats_eth stats; +#endif + bool tx_frames_flushed; + uint16_t dma_desc_tx_head; + uint16_t dma_desc_rx_tail; + sys_slist_t tx_frame_list; + struct net_buf *rx_frag_list[NUM_RX_DMA_DESCRIPTORS]; +#if defined(CONFIG_PTP_CLOCK_XMC4XXX) + const struct device *ptp_clock; +#endif +}; + +struct eth_xmc4xxx_config { + ETH_GLOBAL_TypeDef *regs; + const struct device *phy_dev; + void (*irq_config_func)(void); + const struct pinctrl_dev_config *pcfg; + const uint8_t phy_connection_type; + XMC_ETH_MAC_PORT_CTRL_t port_ctrl; +}; + +struct eth_xmc4xxx_tx_frame { + sys_snode_t node; + struct net_pkt *pkt; + uint16_t tail_index; + uint16_t head_index; +}; + +K_MEM_SLAB_DEFINE_STATIC(tx_frame_slab, sizeof(struct eth_xmc4xxx_tx_frame), + CONFIG_ETH_XMC4XXX_TX_FRAME_POOL_SIZE, 4); + +static XMC_ETH_MAC_DMA_DESC_t __aligned(4) tx_dma_desc[NUM_TX_DMA_DESCRIPTORS]; +static XMC_ETH_MAC_DMA_DESC_t __aligned(4) rx_dma_desc[NUM_RX_DMA_DESCRIPTORS]; + +static inline struct net_if *get_iface(struct eth_xmc4xxx_data *ctx, uint16_t vlan_tag) +{ +#if defined(CONFIG_NET_VLAN) + struct net_if *iface; + + iface = net_eth_get_vlan_iface(ctx->iface, vlan_tag); + if (!iface) { + return ctx->iface; + } + + return iface; +#else + ARG_UNUSED(vlan_tag); + + return ctx->iface; +#endif +} + +static void eth_xmc4xxx_tx_dma_descriptors_init(const struct device *dev) +{ + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + + memset(tx_dma_desc, 0, sizeof(tx_dma_desc)); + + dev_cfg->regs->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t)&tx_dma_desc[0]; + + /* chain the descriptors */ + for (int i = 0; i < NUM_TX_DMA_DESCRIPTORS - 1; i++) { + XMC_ETH_MAC_DMA_DESC_t *dma_desc = &tx_dma_desc[i]; + + dma_desc->buffer2 = (volatile uint32_t)&tx_dma_desc[i + 1]; + } + + /* TER: transmit end of ring - it is the last descriptor in ring */ + tx_dma_desc[NUM_TX_DMA_DESCRIPTORS - 1].status |= ETH_MAC_DMA_TDES0_TER; + tx_dma_desc[NUM_TX_DMA_DESCRIPTORS - 1].buffer2 = (volatile uint32_t)&tx_dma_desc[0]; +} + +static void eth_xmc4xxx_flush_rx(const struct device *dev) +{ + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + struct eth_xmc4xxx_data *dev_data = dev->data; + + dev_cfg->regs->OPERATION_MODE &= ~ETH_OPERATION_MODE_SR_Msk; + + for (int i = 0; i < NUM_RX_DMA_DESCRIPTORS; i++) { + rx_dma_desc[i].status = ETH_MAC_DMA_RDES0_OWN; + } + + dev_cfg->regs->OPERATION_MODE |= ETH_OPERATION_MODE_SR_Msk; + dev_data->dma_desc_rx_tail = 0; +} + +static void eth_xmc4xxx_flush_tx(const struct device *dev) +{ + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + struct eth_xmc4xxx_data *dev_data = dev->data; + sys_snode_t *node; + + LOG_DBG("Flushing tx frames"); + + if (dev_data->tx_frames_flushed) { + return; + } + + dev_cfg->regs->OPERATION_MODE &= ~ETH_OPERATION_MODE_ST_Msk; + + node = sys_slist_get(&dev_data->tx_frame_list); + while (node) { + struct eth_xmc4xxx_tx_frame *tx_frame = SYS_SLIST_CONTAINER(node, tx_frame, node); + + net_pkt_unref(tx_frame->pkt); + k_mem_slab_free(&tx_frame_slab, (void *)tx_frame); + + node = sys_slist_get(&dev_data->tx_frame_list); +#ifdef CONFIG_NET_STATISTICS_ETHERNET + dev_data->stats.errors.tx++; + dev_data->stats.error_details.tx_aborted_errors++; +#endif + } + + k_sem_reset(&dev_data->tx_desc_sem); + + eth_xmc4xxx_tx_dma_descriptors_init(dev); + dev_cfg->regs->OPERATION_MODE |= ETH_OPERATION_MODE_ST_Msk; + dev_data->dma_desc_tx_head = 0; + dev_data->tx_frames_flushed = true; + + for (int i = 0; i < NUM_TX_DMA_DESCRIPTORS; i++) { + k_sem_give(&dev_data->tx_desc_sem); + } +} + +static inline void eth_xmc4xxx_trigger_dma_tx(ETH_GLOBAL_TypeDef *regs) +{ + regs->STATUS = ETH_STATUS_TPS_Msk; + regs->TRANSMIT_POLL_DEMAND = 0; +} + +static inline void eth_xmc4xxx_trigger_dma_rx(ETH_GLOBAL_TypeDef *regs) +{ + regs->STATUS = ETH_STATUS_RU_Msk; + regs->RECEIVE_POLL_DEMAND = 0U; +} + +static int eth_xmc4xxx_send(const struct device *dev, struct net_pkt *pkt) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + struct net_buf *frag; + uint8_t *frag_data; + uint16_t frag_len; + int ret = 0; + XMC_ETH_MAC_DMA_DESC_t *dma_desc = NULL; + struct eth_xmc4xxx_tx_frame *tx_frame; + int num_frags = 0; + bool first_descriptor = false; + + frag = pkt->frags; + while (frag) { + num_frags++; + frag = frag->frags; + } + + if (num_frags > NUM_TX_DMA_DESCRIPTORS) { +#ifdef CONFIG_NET_STATISTICS_ETHERNET + dev_data->stats.error_details.tx_dma_failed++; +#endif + LOG_DBG("Number of fragments exceeds total descriptors. Dropping packet"); + return -ENOMEM; + } + + /* All available frames buffered inside the driver. Apply back pressure in the driver. */ + while (tx_frame_slab.info.num_used == CONFIG_ETH_XMC4XXX_TX_FRAME_POOL_SIZE) { + eth_xmc4xxx_trigger_dma_tx(dev_cfg->regs); + k_yield(); + } + + ret = k_mem_slab_alloc(&tx_frame_slab, (void **)&tx_frame, K_NO_WAIT); + __ASSERT_NO_MSG(ret == 0); + + net_pkt_ref(pkt); + + dev_data->tx_frames_flushed = false; + + first_descriptor = true; + tx_frame->pkt = pkt; + tx_frame->tail_index = dev_data->dma_desc_tx_head; + + frag = pkt->frags; + while (frag) { + ret = k_sem_take(&dev_data->tx_desc_sem, K_FOREVER); + /* isr may call k_sem_reset() */ + if (ret < 0 || dev_data->tx_frames_flushed) { + k_mem_slab_free(&tx_frame_slab, (void **)&tx_frame); + net_pkt_unref(pkt); +#ifdef CONFIG_NET_STATISTICS_ETHERNET + dev_data->stats.error_details.tx_aborted_errors++; +#endif + LOG_DBG("Dropping frame. Buffered Tx frames were flushed in ISR."); + return -EIO; + } + + unsigned int key = irq_lock(); + /* Critical section for dma_desc_tx_head and tx_dma_desc. Isr may */ + /* reinitialize the descriptors and set dma_desc_tx_head to 0 */ + + dma_desc = &tx_dma_desc[dev_data->dma_desc_tx_head]; + + frag_data = frag->data; + frag_len = frag->len; + + dma_desc->buffer1 = (volatile uint32_t)frag_data; + dma_desc->length = frag_len; + + /* give ownership of descriptor back to dma and set checksum offload */ + /* TCH we are using a circular list */ + dma_desc->status = ETH_MAC_DMA_TDES0_CIC | ETH_MAC_DMA_TDES0_TCH; + + if (!first_descriptor) { + /* Delay giving ownership of first frag to DMA. Prevents race condition */ + /* where second other frags are not ready */ + dma_desc->status |= ETH_MAC_DMA_TDES0_OWN; + } else { + dma_desc->status |= ETH_MAC_DMA_TDES0_FS; + +#if defined(CONFIG_NET_GPTP) + struct net_eth_hdr *hdr = NET_ETH_HDR(pkt); + + if (ntohs(hdr->type) == NET_ETH_PTYPE_PTP) { + dma_desc->status |= ETH_MAC_DMA_TDES0_TTSE; + } +#endif + } + first_descriptor = false; + + tx_frame->head_index = dev_data->dma_desc_tx_head; + + MODULO_INC_TX(dev_data->dma_desc_tx_head); + + irq_unlock(key); + + frag = frag->frags; + } + + if (dev_data->tx_frames_flushed) { + k_mem_slab_free(&tx_frame_slab, (void **)&tx_frame); + net_pkt_unref(pkt); +#ifdef CONFIG_NET_STATISTICS_ETHERNET + dev_data->stats.error_details.tx_aborted_errors++; +#endif + LOG_DBG("Dropping frame. Buffered Tx frames were flushed in ISR."); + return -EIO; + } + + unsigned int key = irq_lock(); + + /* label last dma descriptor as last segment and trigger interrupt on last segment */ + dma_desc->status |= ETH_MAC_DMA_TDES0_IC | ETH_MAC_DMA_TDES0_LS; + + /* Finally give ownership of first frag to DMA. After this point the DMA engine */ + /* may transfer the whole frame from RAM to Ethernet */ + tx_dma_desc[tx_frame->tail_index].status |= ETH_MAC_DMA_TDES0_OWN; + + sys_slist_append(&dev_data->tx_frame_list, &tx_frame->node); + + eth_xmc4xxx_trigger_dma_tx(dev_cfg->regs); + + irq_unlock(key); + + return 0; +} + +static struct net_pkt *eth_xmc4xxx_rx_pkt(const struct device *dev) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + struct net_pkt *pkt = NULL; + struct net_buf *new_frag; + + bool eof_found = false; + uint16_t tail; + XMC_ETH_MAC_DMA_DESC_t *dma_desc; + int num_frags = 0; + uint16_t frame_end_index; + struct net_buf *frag, *last_frag = NULL; + + tail = dev_data->dma_desc_rx_tail; + dma_desc = &rx_dma_desc[tail]; + + if (IS_OWNED_BY_DMA_RX(dma_desc)) { + return NULL; + } + + if (!IS_START_OF_FRAME_RX(dma_desc)) { + /* handle this error - missing SOF packet? */ + eth_xmc4xxx_flush_rx(dev); + return NULL; + } + + while (!IS_OWNED_BY_DMA_RX(dma_desc)) { + eof_found = IS_END_OF_FRAME_RX(dma_desc); + num_frags++; + if (eof_found) { + break; + } + + MODULO_INC_RX(tail); + + if (tail == dev_data->dma_desc_rx_tail) { + /* wrapped */ + break; + } + + dma_desc = &rx_dma_desc[tail]; + } + + if (!eof_found) { + return NULL; + } + + frame_end_index = tail; + + pkt = net_pkt_rx_alloc(K_NO_WAIT); + if (pkt == NULL) { +#ifdef CONFIG_NET_STATISTICS_ETHERNET + dev_data->stats.errors.rx++; + dev_data->stats.error_details.rx_no_buffer_count++; +#endif + LOG_DBG("Net packet allocation error"); + /* continue because we still need to read out the packet */ + } + + tail = dev_data->dma_desc_rx_tail; + dma_desc = &rx_dma_desc[tail]; + for (;;) { + if (pkt != NULL) { + uint16_t frag_len = CONFIG_NET_BUF_DATA_SIZE; + + frag = dev_data->rx_frag_list[tail]; + if (tail == frame_end_index) { + frag_len = TOTAL_FRAME_LENGTH(dma_desc) - + CONFIG_NET_BUF_DATA_SIZE * (num_frags - 1); + + if (IS_TIMESTAMP_AVAILABLE_RX(dma_desc)) { + struct net_ptp_time timestamp = { + .second = dma_desc->time_stamp_seconds, + .nanosecond = dma_desc->time_stamp_nanoseconds}; + + net_pkt_set_timestamp(pkt, ×tamp); + net_pkt_set_priority(pkt, NET_PRIORITY_CA); + } + } + + new_frag = net_pkt_get_frag(pkt, CONFIG_NET_BUF_DATA_SIZE, K_NO_WAIT); + if (new_frag == NULL) { +#ifdef CONFIG_NET_STATISTICS_ETHERNET + dev_data->stats.errors.rx++; + dev_data->stats.error_details.rx_buf_alloc_failed++; +#endif + LOG_DBG("Frag allocation error. Increase CONFIG_NET_BUF_RX_COUNT."); + net_pkt_unref(pkt); + pkt = NULL; + } else { + net_buf_add(frag, frag_len); + if (!last_frag) { + net_pkt_frag_insert(pkt, frag); + } else { + net_buf_frag_insert(last_frag, frag); + } + + last_frag = frag; + frag = new_frag; + dev_data->rx_frag_list[tail] = frag; + } + } + + dma_desc->buffer1 = (uint32_t)dev_data->rx_frag_list[tail]->data; + dma_desc->length = dev_data->rx_frag_list[tail]->size | + ETH_RX_DMA_DESC_SECOND_ADDR_CHAINED_MASK; + dma_desc->status = ETH_MAC_DMA_RDES0_OWN; + + if (tail == frame_end_index) { + break; + } + + MODULO_INC_RX(tail); + dma_desc = &rx_dma_desc[tail]; + } + + + MODULO_INC_RX(tail); + dev_data->dma_desc_rx_tail = tail; + + eth_xmc4xxx_trigger_dma_rx(dev_cfg->regs); + + return pkt; +} + +static void eth_xmc4xxx_handle_rx(const struct device *dev) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + struct net_pkt *pkt = NULL; + + for (;;) { + uint16_t vlan_tag = NET_VLAN_TAG_UNSPEC; + + pkt = eth_xmc4xxx_rx_pkt(dev); + if (!pkt) { + return; + } +#if defined(CONFIG_NET_VLAN) + struct net_eth_hdr *hdr = NET_ETH_HDR(pkt); + + if (ntohs(hdr->type) == NET_ETH_PTYPE_VLAN) { + struct net_eth_vlan_hdr *hdr_vlan = (struct net_eth_vlan_hdr *)hdr; + + net_pkt_set_vlan_tci(pkt, ntohs(hdr_vlan->vlan.tci)); + vlan_tag = net_pkt_vlan_tag(pkt); + +#if CONFIG_NET_TC_RX_COUNT > 1 + enum net_priority prio; + + prio = net_vlan2priority(net_pkt_vlan_priority(pkt)); + net_pkt_set_priority(pkt, prio); +#endif + } +#endif /* CONFIG_NET_VLAN */ + if (net_recv_data(get_iface(dev_data, vlan_tag), pkt) < 0) { + eth_stats_update_errors_rx(get_iface(dev_data, vlan_tag)); + net_pkt_unref(pkt); + } + } +} + +static void eth_xmc4xxx_handle_tx(const struct device *dev) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + sys_snode_t *node = sys_slist_peek_head(&dev_data->tx_frame_list); + + while (node) { + struct eth_xmc4xxx_tx_frame *tx_frame = SYS_SLIST_CONTAINER(node, tx_frame, node); + bool owned_by_mcu = true; + uint8_t index; + int num_descriptors; + + if (tx_frame->head_index >= tx_frame->tail_index) { + num_descriptors = tx_frame->head_index - tx_frame->tail_index + 1; + } else { + num_descriptors = tx_frame->head_index + NUM_TX_DMA_DESCRIPTORS - + tx_frame->tail_index + 1; + } + + index = tx_frame->tail_index; + for (int i = 0; i < num_descriptors; i++) { + if (IS_OWNED_BY_DMA_TX(&tx_dma_desc[index])) { + owned_by_mcu = false; + break; + } + + MODULO_INC_TX(index); + } + + if (owned_by_mcu) { +#if defined(CONFIG_NET_GPTP) + XMC_ETH_MAC_DMA_DESC_t *dma_desc = &tx_dma_desc[tx_frame->head_index]; + + if (IS_TIMESTAMP_AVAILABLE_TX(dma_desc)) { + struct net_pkt *pkt = tx_frame->pkt; + + if (atomic_get(&pkt->atomic_ref) > 1) { + struct net_ptp_time timestamp = { + .second = dma_desc->time_stamp_seconds, + .nanosecond = dma_desc->time_stamp_nanoseconds}; + + net_pkt_set_timestamp(pkt, ×tamp); + net_if_add_tx_timestamp(pkt); + } + } +#endif + + for (int i = 0; i < num_descriptors; i++) { + k_sem_give(&dev_data->tx_desc_sem); + } + + sys_slist_get(&dev_data->tx_frame_list); + net_pkt_unref(tx_frame->pkt); + k_mem_slab_free(&tx_frame_slab, (void *)tx_frame); + node = sys_slist_peek_head(&dev_data->tx_frame_list); + } else { + node = NULL; + } + } +} + +static void eth_xmc4xxx_isr(const struct device *dev) +{ + uint32_t lock; + uint32_t status; + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + + lock = irq_lock(); + status = dev_cfg->regs->STATUS; + + if ((status & XMC_ETH_MAC_EVENT_RECEIVE) != 0) { + eth_xmc4xxx_handle_rx(dev); + } + + if ((status & XMC_ETH_MAC_EVENT_TRANSMIT) != 0) { + eth_xmc4xxx_handle_tx(dev); + } + + if ((status & ETH_STATUS_ERROR_TRANSMIT_EVENTS) != 0) { + LOG_ERR("Transmit error event [0x%x]", status); + eth_xmc4xxx_flush_tx(dev); + } + + if ((status & ETH_STATUS_ERROR_RECEIVE_EVENTS) != 0) { + LOG_ERR("Receive error event [0x%x]", status); + eth_xmc4xxx_flush_rx(dev); + } + + dev_cfg->regs->STATUS = status & ETH_STATUS_CLEARABLE_BITS; + + irq_unlock(lock); +} + +static inline void eth_xmc4xxx_enable_tx(ETH_GLOBAL_TypeDef *regs) +{ + regs->OPERATION_MODE |= ETH_OPERATION_MODE_ST_Msk; + regs->MAC_CONFIGURATION |= ETH_MAC_CONFIGURATION_TE_Msk; +} + +static inline void eth_xmc4xxx_enable_rx(ETH_GLOBAL_TypeDef *regs) +{ + regs->OPERATION_MODE |= ETH_OPERATION_MODE_SR_Msk; + regs->MAC_CONFIGURATION |= ETH_MAC_CONFIGURATION_RE_Msk; +} + +static inline void eth_xmc4xxx_set_link(ETH_GLOBAL_TypeDef *regs, struct phy_link_state *state) +{ + uint32_t reg = regs->MAC_CONFIGURATION; + uint32_t val; + + reg &= ~(ETH_MAC_CONFIGURATION_DM_Msk | ETH_MAC_CONFIGURATION_FES_Msk); + + val = PHY_LINK_IS_FULL_DUPLEX(state->speed) ? ETH_LINK_DUPLEX_FULL : + ETH_LINK_DUPLEX_HALF; + reg |= FIELD_PREP(ETH_MAC_CONFIGURATION_DM_Msk, val); + + val = PHY_LINK_IS_SPEED_100M(state->speed) ? ETH_LINK_SPEED_100M : + ETH_LINK_SPEED_10M; + reg |= FIELD_PREP(ETH_MAC_CONFIGURATION_FES_Msk, val); + + regs->MAC_CONFIGURATION = reg; +} + +static void phy_link_state_changed(const struct device *phy_dev, struct phy_link_state *state, + void *user_data) +{ + struct device *dev = user_data; + struct eth_xmc4xxx_data *dev_data = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + bool is_up = state->is_up; + + if (is_up && !dev_data->link_up) { + LOG_INF("Link up"); + dev_data->link_up = true; + net_eth_carrier_on(dev_data->iface); + eth_xmc4xxx_set_link(dev_cfg->regs, state); + } else if (!is_up && dev_data->link_up) { + LOG_INF("Link down"); + dev_data->link_up = false; + net_eth_carrier_off(dev_data->iface); + } +} + +static void eth_xmc4xxx_iface_init(struct net_if *iface) +{ + const struct device *dev = net_if_get_device(iface); + struct eth_xmc4xxx_data *dev_data = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + + dev_data->iface = iface; + + net_if_set_link_addr(iface, dev_data->mac_addr, sizeof(dev_data->mac_addr), + NET_LINK_ETHERNET); + + ethernet_init(iface); + + dev_cfg->irq_config_func(); + + /* Do not start the interface until PHY link is up */ + net_if_carrier_off(iface); + + phy_link_callback_set(dev_cfg->phy_dev, &phy_link_state_changed, (void *)dev); + + dev_cfg->regs->INTERRUPT_ENABLE |= ETH_STATUS_ALL_EVENTS; + + eth_xmc4xxx_enable_tx(dev_cfg->regs); + eth_xmc4xxx_enable_rx(dev_cfg->regs); +} + +#if defined(CONFIG_NET_STATISTICS_ETHERNET) +static struct net_stats_eth *eth_xmc4xxx_stats(const struct device *dev) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + + return &dev_data->stats; +} +#endif + +static inline void eth_xmc4xxx_free_rx_bufs(const struct device *dev) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + + for (int i = 0; i < NUM_RX_DMA_DESCRIPTORS; i++) { + if (dev_data->rx_frag_list[i]) { + net_buf_unref(dev_data->rx_frag_list[i]); + dev_data->rx_frag_list[i] = NULL; + } + } +} + +static int eth_xmc4xxx_rx_dma_descriptors_init(const struct device *dev) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + + dev_cfg->regs->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t)&rx_dma_desc[0]; + + for (int i = 0; i < NUM_RX_DMA_DESCRIPTORS - 1; i++) { + XMC_ETH_MAC_DMA_DESC_t *dma_desc = &rx_dma_desc[i]; + + dma_desc->buffer2 = (volatile uint32_t)&rx_dma_desc[i + 1]; + } + + rx_dma_desc[NUM_RX_DMA_DESCRIPTORS - 1].status |= ETH_MAC_DMA_TDES0_TER; + rx_dma_desc[NUM_RX_DMA_DESCRIPTORS - 1].buffer2 = (volatile uint32_t)&rx_dma_desc[0]; + + for (int i = 0; i < NUM_RX_DMA_DESCRIPTORS; i++) { + XMC_ETH_MAC_DMA_DESC_t *dma_desc = &rx_dma_desc[i]; + struct net_buf *rx_buf = net_pkt_get_reserve_rx_data(CONFIG_NET_BUF_DATA_SIZE, + K_NO_WAIT); + + if (rx_buf == NULL) { + eth_xmc4xxx_free_rx_bufs(dev); + LOG_ERR("Failed to reserve data net buffers"); + return -ENOBUFS; + } + + dev_data->rx_frag_list[i] = rx_buf; + dma_desc->buffer1 = (uint32_t)rx_buf->data; + dma_desc->length = rx_buf->size | ETH_RX_DMA_DESC_SECOND_ADDR_CHAINED_MASK; + dma_desc->status = ETH_MAC_DMA_RDES0_OWN; + } + + return 0; +} + +static inline int eth_xmc4xxx_reset(const struct device *dev) +{ + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + + dev_cfg->regs->BUS_MODE |= ETH_BUS_MODE_SWR_Msk; + + /* reset may fail if the clocks are not properly setup */ + if (!WAIT_FOR((dev_cfg->regs->BUS_MODE & ETH_BUS_MODE_SWR_Msk) == 0, + ETH_RESET_TIMEOUT_USEC,)) { + return -ETIMEDOUT; + } + + return 0; +} + +static inline void eth_xmc4xxx_set_mac_address(ETH_GLOBAL_TypeDef *regs, uint8_t *const addr) +{ + regs->MAC_ADDRESS0_HIGH = addr[4] | (addr[5] << 8); + regs->MAC_ADDRESS0_LOW = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); +} + +static inline void eth_xmc4xxx_mask_unused_interrupts(ETH_GLOBAL_TypeDef *regs) +{ + /* Disable Mac Management Counter (MMC) interrupt events */ + regs->MMC_TRANSMIT_INTERRUPT_MASK = ETH_MAC_DISABLE_MMC_INTERRUPT_MSK; + regs->MMC_RECEIVE_INTERRUPT_MASK = ETH_MAC_DISABLE_MMC_INTERRUPT_MSK; + + /* IPC - Receive IP checksum checker */ + regs->MMC_IPC_RECEIVE_INTERRUPT_MASK = ETH_MAC_DISABLE_MMC_IPC_RECEIVE_INTERRUPT_MSK; + + /* Disable PMT and timestamp interrupt events */ + regs->INTERRUPT_MASK = ETH_INTERRUPT_MASK_PMTIM_Msk | ETH_INTERRUPT_MASK_TSIM_Msk; +} + +static inline int eth_xmc4xxx_init_timestamp_control_reg(ETH_GLOBAL_TypeDef *regs) +{ +#if defined(CONFIG_NET_GPTP) + regs->TIMESTAMP_CONTROL = ETH_TIMESTAMP_CONTROL_TSENA_Msk | + ETH_TIMESTAMP_CONTROL_TSENALL_Msk; +#endif + +#if defined(CONFIG_PTP_CLOCK_XMC4XXX) + /* use fine control */ + regs->TIMESTAMP_CONTROL |= ETH_TIMESTAMP_CONTROL_TSCFUPDT_Msk | + ETH_TIMESTAMP_CONTROL_TSCTRLSSR_Msk; + + /* make ptp run at 50MHz - implies 20ns increment for each increment of the */ + /* sub_second_register */ + regs->SUB_SECOND_INCREMENT = 20; + + /* f_out = f_cpu * K / 2^32, where K = TIMESTAMP_ADDEND. Target F_out = 50MHz */ + /* Therefore, K = ceil(f_out * 2^32 / f_cpu) */ + + uint32_t f_cpu = XMC_SCU_CLOCK_GetSystemClockFrequency(); + uint32_t K = (BIT64(32) * ETH_PTP_CLOCK_FREQUENCY + f_cpu / 2) / f_cpu; + + regs->TIMESTAMP_ADDEND = K; + + /* Addend register update */ + regs->TIMESTAMP_CONTROL |= ETH_TIMESTAMP_CONTROL_TSADDREG_Msk; + if (!WAIT_FOR((regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSADDREG_Msk) == 0, + ETH_TIMESTAMP_CONTROL_REG_TIMEOUT_USEC,)) { + return -ETIMEDOUT; + } + + regs->TIMESTAMP_CONTROL |= ETH_TIMESTAMP_CONTROL_TSINIT_Msk; + if (!WAIT_FOR((regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSINIT_Msk) == 0, + ETH_TIMESTAMP_CONTROL_REG_TIMEOUT_USEC,)) { + return -ETIMEDOUT; + } +#endif + return 0; +} + +static int eth_xmc4xxx_init(const struct device *dev) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + XMC_ETH_MAC_PORT_CTRL_t port_ctrl; + int ret; + + sys_slist_init(&dev_data->tx_frame_list); + k_sem_init(&dev_data->tx_desc_sem, NUM_TX_DMA_DESCRIPTORS, + NUM_TX_DMA_DESCRIPTORS); + + if (!device_is_ready(dev_cfg->phy_dev)) { + LOG_ERR("Phy device not ready"); + return -ENODEV; + } + + /* get the port control initialized by MDIO driver */ + port_ctrl.raw = ETH0_CON->CON; + port_ctrl.raw |= dev_cfg->port_ctrl.raw; + + XMC_ETH_MAC_Disable(NULL); + ret = pinctrl_apply_state(dev_cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } + + XMC_ETH_MAC_SetPortControl(NULL, port_ctrl); + XMC_ETH_MAC_Enable(NULL); + + ret = eth_xmc4xxx_reset(dev); + if (ret != 0) { + LOG_ERR("Error resetting ethernet [%d]", ret); + return ret; + } + + /* Initialize MAC configuration */ + /* enable checksum offload */ + dev_cfg->regs->MAC_CONFIGURATION = ETH_MAC_CONFIGURATION_IPC_Msk; + + /* disable jumbo frames */ + dev_cfg->regs->MAC_CONFIGURATION &= ~ETH_MAC_CONFIGURATION_JE_Msk; + + + /* Initialize Filter registers - disable zero quanta pause*/ + dev_cfg->regs->FLOW_CONTROL = ETH_FLOW_CONTROL_DZPQ_Msk; + + /* rsf - receive store and forward */ + /* tsf - transmit store and forward */ + dev_cfg->regs->OPERATION_MODE = ETH_OPERATION_MODE_RSF_Msk | ETH_OPERATION_MODE_TSF_Msk | + ETH_OPERATION_MODE_OSF_Msk; + + /* Increase enhanced descriptor to 8 WORDS, required when the Advanced */ + /* Time-Stamp feature or Full IPC Offload Engine is enabled */ + dev_cfg->regs->BUS_MODE = ETH_BUS_MODE_ATDS_Msk | ETH_BUS_MODE_AAL_Msk | + ETH_BUS_MODE_FB_Msk | (0x20 << ETH_BUS_MODE_PBL_Pos); + + eth_xmc4xxx_tx_dma_descriptors_init(dev); + ret = eth_xmc4xxx_rx_dma_descriptors_init(dev); + if (ret != 0) { + return ret; + } + + /* Clear interrupts */ + dev_cfg->regs->STATUS = ETH_STATUS_CLEARABLE_BITS; + + eth_xmc4xxx_mask_unused_interrupts(dev_cfg->regs); + +#if !DT_INST_NODE_HAS_PROP(0, local_mac_address) + gen_random_mac(dev_data->mac_addr, INFINEON_OUI_B0, INFINEON_OUI_B1, INFINEON_OUI_B2); +#endif + eth_xmc4xxx_set_mac_address(dev_cfg->regs, dev_data->mac_addr); + + uint32_t reg = dev_cfg->regs->MAC_FRAME_FILTER; + /* enable reception of broadcast frames */ + reg &= ~ETH_MAC_FRAME_FILTER_DBF_Msk; + /* pass all multicast frames */ + reg |= ETH_MAC_FRAME_FILTER_PM_Msk; + dev_cfg->regs->MAC_FRAME_FILTER = reg; + + return eth_xmc4xxx_init_timestamp_control_reg(dev_cfg->regs); +} + +static enum ethernet_hw_caps eth_xmc4xxx_capabilities(const struct device *dev) +{ + ARG_UNUSED(dev); + enum ethernet_hw_caps caps = ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T | + ETHERNET_HW_TX_CHKSUM_OFFLOAD | ETHERNET_HW_RX_CHKSUM_OFFLOAD; + +#if defined(CONFIG_PTP_CLOCK_XMC4XXX) + caps |= ETHERNET_PTP; +#endif + +#if defined(CONFIG_NET_VLAN) + caps |= ETHERNET_HW_VLAN; +#endif + + return caps; +} + +static int eth_xmc4xxx_set_config(const struct device *dev, enum ethernet_config_type type, + const struct ethernet_config *config) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + + switch (type) { + case ETHERNET_CONFIG_TYPE_MAC_ADDRESS: + memcpy(dev_data->mac_addr, config->mac_address.addr, sizeof(dev_data->mac_addr)); + LOG_INF("%s MAC set to %02x:%02x:%02x:%02x:%02x:%02x", dev->name, + dev_data->mac_addr[0], dev_data->mac_addr[1], dev_data->mac_addr[2], + dev_data->mac_addr[3], dev_data->mac_addr[4], dev_data->mac_addr[5]); + + eth_xmc4xxx_set_mac_address(dev_cfg->regs, dev_data->mac_addr); + net_if_set_link_addr(dev_data->iface, dev_data->mac_addr, + sizeof(dev_data->mac_addr), NET_LINK_ETHERNET); + return 0; + default: + break; + } + + return -ENOTSUP; +} + +static void eth_xmc4xxx_irq_config(void) +{ + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), eth_xmc4xxx_isr, + DEVICE_DT_INST_GET(0), 0); + irq_enable(DT_INST_IRQN(0)); +} + +#if defined(CONFIG_PTP_CLOCK_XMC4XXX) +static const struct device *eth_xmc4xxx_get_ptp_clock(const struct device *dev) +{ + struct eth_xmc4xxx_data *dev_data = dev->data; + + return dev_data->ptp_clock; +} +#endif + + +#if defined(CONFIG_ETH_XMC4XXX_VLAN_HW_FILTER) +int eth_xmc4xxx_vlan_setup(const struct device *dev, struct net_if *iface, uint16_t tag, + bool enable) +{ + ARG_UNUSED(iface); + const struct eth_xmc4xxx_config *dev_cfg = dev->config; + + LOG_INF("Configuring vlan %d", tag); + + if (enable) { + dev_cfg->regs->VLAN_TAG = FIELD_PREP(ETH_VLAN_TAG_VL_Msk, tag) | + ETH_VLAN_TAG_ETV_Msk | + ETH_VLAN_TAG_ESVL_Msk; + dev_cfg->regs->MAC_FRAME_FILTER |= ETH_MAC_FRAME_FILTER_VTFE_Msk; + } else { + dev_cfg->regs->VLAN_TAG = 0; + dev_cfg->regs->MAC_FRAME_FILTER &= ~ETH_MAC_FRAME_FILTER_VTFE_Msk; + } + + return 0; +} +#endif + +static const struct ethernet_api eth_xmc4xxx_api = { + .iface_api.init = eth_xmc4xxx_iface_init, + .send = eth_xmc4xxx_send, + .set_config = eth_xmc4xxx_set_config, + .get_capabilities = eth_xmc4xxx_capabilities, +#if defined(CONFIG_NET_STATISTICS_ETHERNET) + .get_stats = eth_xmc4xxx_stats, +#endif +#if defined(CONFIG_PTP_CLOCK_XMC4XXX) + .get_ptp_clock = eth_xmc4xxx_get_ptp_clock, +#endif +#if defined(CONFIG_ETH_XMC4XXX_VLAN_HW_FILTER) + .vlan_setup = eth_xmc4xxx_vlan_setup, +#endif +}; + +PINCTRL_DT_INST_DEFINE(0); + +static struct eth_xmc4xxx_config eth_xmc4xxx_config = { + .regs = (ETH_GLOBAL_TypeDef *)DT_REG_ADDR(DT_INST_PARENT(0)), + .irq_config_func = eth_xmc4xxx_irq_config, + .phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, phy_handle)), + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), + .port_ctrl = { + .rxd0 = DT_INST_ENUM_IDX(0, rxd0_port_ctrl), + .rxd1 = DT_INST_ENUM_IDX(0, rxd1_port_ctrl), + .rxd2 = DT_INST_ENUM_IDX_OR(0, rxd2_port_ctrl, 0), + .rxd3 = DT_INST_ENUM_IDX_OR(0, rxd3_port_ctrl, 0), + .clk_rmii = DT_INST_ENUM_IDX(0, rmii_rx_clk_port_ctrl), + .crs_dv = DT_INST_ENUM_IDX(0, crs_rx_dv_port_ctrl), + .crs = DT_INST_ENUM_IDX_OR(0, crs_port_ctrl, 0), + .rxer = DT_INST_ENUM_IDX(0, rxer_port_ctrl), + .col = DT_INST_ENUM_IDX_OR(0, col_port_ctrl, 0), + .clk_tx = DT_INST_ENUM_IDX_OR(0, tx_clk_port_ctrl, 0), + .mode = DT_INST_ENUM_IDX_OR(0, phy_connection_type, 0), + } +}; + +static struct eth_xmc4xxx_data eth_xmc4xxx_data = { + .mac_addr = DT_INST_PROP_OR(0, local_mac_address, {0}), +}; + +ETH_NET_DEVICE_DT_INST_DEFINE(0, eth_xmc4xxx_init, NULL, ð_xmc4xxx_data, ð_xmc4xxx_config, + CONFIG_ETH_INIT_PRIORITY, ð_xmc4xxx_api, NET_ETH_MTU); + +#if defined(CONFIG_PTP_CLOCK_XMC4XXX) + +struct ptp_context { + const struct device *eth_dev; +}; + +static struct ptp_context ptp_xmc4xxx_context_0; + +static int eth_xmc4xxx_ptp_clock_set(const struct device *dev, struct net_ptp_time *tm) +{ + struct ptp_context *ptp_context = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = ptp_context->eth_dev->config; + + dev_cfg->regs->SYSTEM_TIME_NANOSECONDS_UPDATE = tm->nanosecond; + dev_cfg->regs->SYSTEM_TIME_SECONDS_UPDATE = tm->second; + + dev_cfg->regs->TIMESTAMP_CONTROL |= ETH_TIMESTAMP_CONTROL_TSINIT_Msk; + if (!WAIT_FOR((dev_cfg->regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSINIT_Msk) == 0, + ETH_TIMESTAMP_CONTROL_REG_TIMEOUT_USEC,)) { + return -ETIMEDOUT; + } + + return 0; +} + +static int eth_xmc4xxx_ptp_clock_get(const struct device *dev, struct net_ptp_time *tm) +{ + struct ptp_context *ptp_context = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = ptp_context->eth_dev->config; + + uint32_t nanosecond_0 = dev_cfg->regs->SYSTEM_TIME_NANOSECONDS; + uint32_t second_0 = dev_cfg->regs->SYSTEM_TIME_SECONDS; + + uint32_t nanosecond_1 = dev_cfg->regs->SYSTEM_TIME_NANOSECONDS; + uint32_t second_1 = dev_cfg->regs->SYSTEM_TIME_SECONDS; + + /* check that there is no roll over while we read the timestamp. If roll over happens */ + /* just choose the later value */ + if (second_0 == second_1) { + tm->second = second_0; + tm->nanosecond = nanosecond_0; + } else { + tm->second = second_1; + tm->nanosecond = nanosecond_1; + } + + return 0; +} + +static int eth_xmc4xxx_ptp_clock_adjust(const struct device *dev, int increment) +{ + struct ptp_context *ptp_context = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = ptp_context->eth_dev->config; + uint32_t increment_tmp; + + if ((increment <= -(int)NSEC_PER_SEC) || (increment >= (int)NSEC_PER_SEC)) { + return -EINVAL; + } + + if (increment < 0) { + increment_tmp = -increment; + increment_tmp |= ETH_SYSTEM_TIME_NANOSECONDS_UPDATE_ADDSUB_Msk; + } else { + increment_tmp = increment; + } + + dev_cfg->regs->SYSTEM_TIME_NANOSECONDS_UPDATE = increment_tmp; + dev_cfg->regs->SYSTEM_TIME_SECONDS_UPDATE = 0; + + dev_cfg->regs->TIMESTAMP_CONTROL |= ETH_TIMESTAMP_CONTROL_TSUPDT_Msk; + if (!WAIT_FOR((dev_cfg->regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSUPDT_Msk) == 0, + ETH_TIMESTAMP_CONTROL_REG_TIMEOUT_USEC,)) { + return -ETIMEDOUT; + } + + return 0; +} + +static int eth_xmc4xxx_ptp_clock_rate_adjust(const struct device *dev, double ratio) +{ + struct ptp_context *ptp_context = dev->data; + const struct eth_xmc4xxx_config *dev_cfg = ptp_context->eth_dev->config; + uint64_t K = dev_cfg->regs->TIMESTAMP_ADDEND; + + if (ratio < ETH_PTP_RATE_ADJUST_RATIO_MIN || ratio > ETH_PTP_RATE_ADJUST_RATIO_MAX) { + return -EINVAL; + } + + /* f_out = f_cpu * K / 2^32, where K = TIMESTAMP_ADDEND. Target F_out = 50MHz */ + K = K * ratio + 0.5; + if (K > UINT32_MAX) { + return -EINVAL; + } + dev_cfg->regs->TIMESTAMP_ADDEND = K; + + /* Addend register update */ + dev_cfg->regs->TIMESTAMP_CONTROL |= ETH_TIMESTAMP_CONTROL_TSADDREG_Msk; + if (!WAIT_FOR((dev_cfg->regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSADDREG_Msk) == 0, + ETH_TIMESTAMP_CONTROL_REG_TIMEOUT_USEC,)) { + return -ETIMEDOUT; + } + + return 0; +} + +static const struct ptp_clock_driver_api ptp_api_xmc4xxx = { + .set = eth_xmc4xxx_ptp_clock_set, + .get = eth_xmc4xxx_ptp_clock_get, + .adjust = eth_xmc4xxx_ptp_clock_adjust, + .rate_adjust = eth_xmc4xxx_ptp_clock_rate_adjust, +}; + +static int ptp_clock_xmc4xxx_init(const struct device *port) +{ + const struct device *const eth_dev = DEVICE_DT_INST_GET(0); + struct eth_xmc4xxx_data *dev_data = eth_dev->data; + struct ptp_context *ptp_context = port->data; + + dev_data->ptp_clock = port; + ptp_context->eth_dev = eth_dev; + + return 0; +} + +DEVICE_DEFINE(xmc4xxx_ptp_clock_0, PTP_CLOCK_NAME, ptp_clock_xmc4xxx_init, NULL, + &ptp_xmc4xxx_context_0, NULL, POST_KERNEL, CONFIG_PTP_CLOCK_INIT_PRIORITY, + &ptp_api_xmc4xxx); + +#endif /* CONFIG_PTP_CLOCK_XMC4XXX */ diff --git a/drivers/flash/Kconfig.nordic_qspi_nor b/drivers/flash/Kconfig.nordic_qspi_nor index aac9830835a7cca..ff652f6082298bc 100644 --- a/drivers/flash/Kconfig.nordic_qspi_nor +++ b/drivers/flash/Kconfig.nordic_qspi_nor @@ -50,4 +50,13 @@ config NORDIC_QSPI_NOR_XIP QSPI NOR flash chip is executed until the driver has been setup. This will also disable power management for the QSPI NOR flash chip. +config NORDIC_QSPI_NOR_TIMEOUT_MS + int "Timeout for QSPI operations (ms)" + default 500 + help + The QSPI peripheral operation timeout in milliseconds. + Primarily intended for long running operations such as + a flash sector erase. The 500 ms default allows for + most typical NOR flash chips to erase a sector. + endif # NORDIC_QSPI_NOR diff --git a/drivers/flash/flash_stm32l4x.c b/drivers/flash/flash_stm32l4x.c index ead57fb3df41c3a..e82bf1db30392b2 100644 --- a/drivers/flash/flash_stm32l4x.c +++ b/drivers/flash/flash_stm32l4x.c @@ -23,7 +23,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #if !defined(STM32L4R5xx) && !defined(STM32L4R7xx) && !defined(STM32L4R9xx) && \ !defined(STM32L4S5xx) && !defined(STM32L4S7xx) && !defined(STM32L4S9xx) && \ - !defined(STM32L4Q5xx) + !defined(STM32L4Q5xx) && !defined(STM32L4P5xx) #define STM32L4X_PAGE_SHIFT 11 #else #define STM32L4X_PAGE_SHIFT 12 diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index d6695989857f677..c0e8c397d8e9ce4 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -1090,6 +1090,10 @@ static int qspi_nor_init(const struct device *dev) qspi_clock_div_restore(); + if (!IS_ENABLED(CONFIG_NORDIC_QSPI_NOR_XIP) && nrfx_qspi_init_check()) { + (void)nrfx_qspi_deactivate(); + } + #ifdef CONFIG_PM_DEVICE_RUNTIME int rc2 = pm_device_runtime_enable(dev); @@ -1382,6 +1386,7 @@ static const struct qspi_nor_config qspi_nor_dev_config = { .sck_delay = DT_INST_PROP(0, sck_delay), .spi_mode = INST_0_SPI_MODE, }, + .nrfx_cfg.timeout = CONFIG_NORDIC_QSPI_NOR_TIMEOUT_MS, .size = INST_0_BYTES, .id = DT_INST_PROP(0, jedec_id), diff --git a/drivers/flash/spi_nor.c b/drivers/flash/spi_nor.c index 1658fce10398505..06518175e45abad 100644 --- a/drivers/flash/spi_nor.c +++ b/drivers/flash/spi_nor.c @@ -659,6 +659,7 @@ static int mxicy_configure(const struct device *dev, const uint8_t *jedec_id) ret = mxicy_rdcr(dev); if (ret < 0) { + release_device(dev); return ret; } current_cr = ret; @@ -1231,6 +1232,7 @@ static int spi_nor_configure(const struct device *dev) rc = exit_dpd(dev); if (rc < 0) { LOG_ERR("Failed to exit DPD (%d)", rc); + release_device(dev); return -ENODEV; } @@ -1280,12 +1282,12 @@ static int spi_nor_configure(const struct device *dev) rc = spi_nor_wrsr(dev, rc & ~cfg->has_lock); } + release_device(dev); + if (rc != 0) { LOG_ERR("BP clear failed: %d\n", rc); return -ENODEV; } - - release_device(dev); } #ifdef CONFIG_SPI_NOR_SFDP_MINIMAL diff --git a/drivers/fpga/fpga_zynqmp.c b/drivers/fpga/fpga_zynqmp.c index 8da54462fae6b14..8181edf5c75b065 100644 --- a/drivers/fpga/fpga_zynqmp.c +++ b/drivers/fpga/fpga_zynqmp.c @@ -293,7 +293,7 @@ static int zynqmp_fpga_load(const struct device *dev, uint32_t *image_ptr, } for (int i = 0; i < (img_size / 4); i++) { - *(BITSTREAM + i) = __bswap_32(*(addr + i)); + *(BITSTREAM + i) = BSWAP_32(*(addr + i)); } init_pcap(dev); diff --git a/drivers/gpio/Kconfig.nrfx b/drivers/gpio/Kconfig.nrfx index 356c43cb5fa1fc3..760a45204fdff48 100644 --- a/drivers/gpio/Kconfig.nrfx +++ b/drivers/gpio/Kconfig.nrfx @@ -5,7 +5,12 @@ menuconfig GPIO_NRFX bool "nRF GPIO driver" default y depends on DT_HAS_NORDIC_NRF_GPIO_ENABLED - select NRFX_GPIOTE + select NRFX_GPIOTE0 if HAS_HW_NRF_GPIOTE0 + select NRFX_GPIOTE1 if HAS_HW_NRF_GPIOTE1 + select NRFX_GPIOTE20 if HAS_HW_NRF_GPIOTE20 + select NRFX_GPIOTE30 if HAS_HW_NRF_GPIOTE30 + select NRFX_GPIOTE130 if HAS_HW_NRF_GPIOTE130 + select NRFX_GPIOTE131 if HAS_HW_NRF_GPIOTE131 help Enable GPIO driver for nRF line of MCUs. diff --git a/drivers/gpio/gpio_nrfx.c b/drivers/gpio/gpio_nrfx.c index 0aa282dda37dc31..d89c964cc90a8fb 100644 --- a/drivers/gpio/gpio_nrfx.c +++ b/drivers/gpio/gpio_nrfx.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ + #define DT_DRV_COMPAT nordic_nrf_gpio #include @@ -25,6 +26,7 @@ struct gpio_nrfx_cfg { NRF_GPIO_Type *port; uint32_t edge_sense; uint8_t port_num; + nrfx_gpiote_t gpiote; }; static inline struct gpio_nrfx_data *get_port_data(const struct device *port) @@ -37,131 +39,139 @@ static inline const struct gpio_nrfx_cfg *get_port_cfg(const struct device *port return port->config; } -static int get_drive(gpio_flags_t flags, nrf_gpio_pin_drive_t *drive) +static bool has_gpiote(const struct gpio_nrfx_cfg *cfg) +{ + return cfg->gpiote.p_reg != NULL; +} + +static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags) +{ + if (flags & GPIO_PULL_UP) { + return NRF_GPIO_PIN_PULLUP; + } else if (flags & GPIO_PULL_DOWN) { + return NRF_GPIO_PIN_PULLDOWN; + } + + return NRF_GPIO_PIN_NOPULL; +} + +static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, + gpio_flags_t flags) { + nrfx_err_t err = NRFX_SUCCESS; + uint8_t ch; + bool free_ch = false; + const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); + 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; + switch (flags & (NRF_GPIO_DRIVE_MSK | GPIO_OPEN_DRAIN)) { case NRF_GPIO_DRIVE_S0S1: - *drive = NRF_GPIO_PIN_S0S1; + drive = NRF_GPIO_PIN_S0S1; break; case NRF_GPIO_DRIVE_S0H1: - *drive = NRF_GPIO_PIN_S0H1; + drive = NRF_GPIO_PIN_S0H1; break; case NRF_GPIO_DRIVE_H0S1: - *drive = NRF_GPIO_PIN_H0S1; + drive = NRF_GPIO_PIN_H0S1; break; case NRF_GPIO_DRIVE_H0H1: - *drive = NRF_GPIO_PIN_H0H1; + drive = NRF_GPIO_PIN_H0H1; break; case NRF_GPIO_DRIVE_S0 | GPIO_OPEN_DRAIN: - *drive = NRF_GPIO_PIN_S0D1; + drive = NRF_GPIO_PIN_S0D1; break; case NRF_GPIO_DRIVE_H0 | GPIO_OPEN_DRAIN: - *drive = NRF_GPIO_PIN_H0D1; + drive = NRF_GPIO_PIN_H0D1; break; case NRF_GPIO_DRIVE_S1 | GPIO_OPEN_SOURCE: - *drive = NRF_GPIO_PIN_D0S1; + drive = NRF_GPIO_PIN_D0S1; break; case NRF_GPIO_DRIVE_H1 | GPIO_OPEN_SOURCE: - *drive = NRF_GPIO_PIN_D0H1; + drive = NRF_GPIO_PIN_D0H1; break; default: return -EINVAL; } - return 0; -} - -static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags) -{ - if (flags & GPIO_PULL_UP) { - return NRF_GPIO_PIN_PULLUP; - } else if (flags & GPIO_PULL_DOWN) { - return NRF_GPIO_PIN_PULLDOWN; + if (flags & GPIO_OUTPUT_INIT_HIGH) { + nrf_gpio_port_out_set(cfg->port, BIT(pin)); + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + nrf_gpio_port_out_clear(cfg->port, BIT(pin)); } - return NRF_GPIO_PIN_NOPULL; -} + if (!has_gpiote(cfg)) { + nrf_gpio_pin_dir_t dir = (flags & GPIO_OUTPUT) + ? NRF_GPIO_PIN_DIR_OUTPUT + : NRF_GPIO_PIN_DIR_INPUT; + nrf_gpio_pin_input_t input = (flags & GPIO_INPUT) + ? NRF_GPIO_PIN_INPUT_CONNECT + : NRF_GPIO_PIN_INPUT_DISCONNECT; -static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, - gpio_flags_t flags) -{ - nrfx_err_t err = NRFX_SUCCESS; - uint8_t ch; - bool free_ch = false; - const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); - nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP(cfg->port_num, pin); + nrf_gpio_reconfigure(abs_pin, &dir, &input, &pull, &drive, NULL); + return 0; + } /* Get the GPIOTE channel associated with this pin, if any. It needs * to be freed when the pin is reconfigured or disconnected. */ if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT)) { - err = nrfx_gpiote_channel_get(abs_pin, &ch); + err = nrfx_gpiote_channel_get(&cfg->gpiote, abs_pin, &ch); free_ch = (err == NRFX_SUCCESS); } if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == GPIO_DISCONNECTED) { /* Ignore the error code. The pin may not have been used. */ - (void)nrfx_gpiote_pin_uninit(abs_pin); - - if (free_ch) { - err = nrfx_gpiote_channel_free(ch); - __ASSERT_NO_MSG(err == NRFX_SUCCESS); + (void)nrfx_gpiote_pin_uninit(&cfg->gpiote, abs_pin); + } else { + /* Remove previously configured trigger when pin is reconfigured. */ + if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT)) { + nrfx_gpiote_trigger_config_t trigger_config = { + .trigger = NRFX_GPIOTE_TRIGGER_NONE, + }; + nrfx_gpiote_input_pin_config_t input_pin_config = { + .p_trigger_config = &trigger_config, + }; + + err = nrfx_gpiote_input_configure(&cfg->gpiote, + abs_pin, &input_pin_config); + if (err != NRFX_SUCCESS) { + return -EINVAL; + } } - return 0; - } - - if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT)) { - nrfx_gpiote_trigger_config_t trigger_config = { - .trigger = NRFX_GPIOTE_TRIGGER_NONE - }; + if (flags & GPIO_OUTPUT) { + nrfx_gpiote_output_config_t output_config = { + .drive = drive, + .input_connect = (flags & GPIO_INPUT) + ? NRF_GPIO_PIN_INPUT_CONNECT + : NRF_GPIO_PIN_INPUT_DISCONNECT, + .pull = pull, + }; + + err = nrfx_gpiote_output_configure(&cfg->gpiote, + abs_pin, &output_config, NULL); + } else { + nrfx_gpiote_input_pin_config_t input_pin_config = { + .p_pull_config = &pull, + }; + + err = nrfx_gpiote_input_configure(&cfg->gpiote, + abs_pin, &input_pin_config); + } - /* Remove previously configured trigger when pin is reconfigured. */ - err = nrfx_gpiote_input_configure(abs_pin, NULL, &trigger_config, NULL); if (err != NRFX_SUCCESS) { return -EINVAL; } - - if (free_ch) { - err = nrfx_gpiote_channel_free(ch); - __ASSERT_NO_MSG(err == NRFX_SUCCESS); - } } - if (flags & GPIO_OUTPUT) { - nrf_gpio_pin_drive_t drive; - int rv = get_drive(flags, &drive); - - if (rv != 0) { - return rv; - } - - nrfx_gpiote_output_config_t output_config = { - .drive = drive, - .input_connect = (flags & GPIO_INPUT) ? - NRF_GPIO_PIN_INPUT_CONNECT : - NRF_GPIO_PIN_INPUT_DISCONNECT, - .pull = get_pull(flags) - }; - - - if (flags & GPIO_OUTPUT_INIT_HIGH) { - nrf_gpio_port_out_set(cfg->port, BIT(pin)); - } else if (flags & GPIO_OUTPUT_INIT_LOW) { - nrf_gpio_port_out_clear(cfg->port, BIT(pin)); - } - - err = nrfx_gpiote_output_configure(abs_pin, &output_config, NULL); - return (err != NRFX_SUCCESS) ? -EINVAL : 0; + if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT) && free_ch) { + err = nrfx_gpiote_channel_free(&cfg->gpiote, ch); + __ASSERT_NO_MSG(err == NRFX_SUCCESS); } - nrfx_gpiote_input_config_t input_config = { - .pull = get_pull(flags) - }; - - err = nrfx_gpiote_input_configure(abs_pin, &input_config, NULL, NULL); - - return (err != NRFX_SUCCESS) ? -EINVAL : 0; + return 0; } static int gpio_nrfx_port_get_raw(const struct device *port, @@ -242,12 +252,17 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port, enum gpio_int_mode mode, enum gpio_int_trig trig) { - uint32_t abs_pin = NRF_GPIO_PIN_MAP(get_port_cfg(port)->port_num, pin); + const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); + uint32_t abs_pin = NRF_GPIO_PIN_MAP(cfg->port_num, pin); nrfx_err_t err; uint8_t ch; + if (!has_gpiote(cfg)) { + return -ENOTSUP; + } + if (mode == GPIO_INT_MODE_DISABLED) { - nrfx_gpiote_trigger_disable(abs_pin); + nrfx_gpiote_trigger_disable(&cfg->gpiote, abs_pin); return 0; } @@ -255,16 +270,19 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port, nrfx_gpiote_trigger_config_t trigger_config = { .trigger = get_trigger(mode, trig), }; + nrfx_gpiote_input_pin_config_t input_pin_config = { + .p_trigger_config = &trigger_config, + }; /* If edge mode is to be used and pin is not configured to use sense for * edge use IN event. */ - if (!(BIT(pin) & get_port_cfg(port)->edge_sense) && + if (!(BIT(pin) & cfg->edge_sense) && (mode == GPIO_INT_MODE_EDGE) && (nrf_gpio_pin_dir_get(abs_pin) == NRF_GPIO_PIN_DIR_INPUT)) { - err = nrfx_gpiote_channel_get(abs_pin, &ch); + err = nrfx_gpiote_channel_get(&cfg->gpiote, abs_pin, &ch); if (err == NRFX_ERROR_INVALID_PARAM) { - err = nrfx_gpiote_channel_alloc(&ch); + err = nrfx_gpiote_channel_alloc(&cfg->gpiote, &ch); if (err != NRFX_SUCCESS) { return -ENOMEM; } @@ -273,12 +291,12 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port, trigger_config.p_in_channel = &ch; } - err = nrfx_gpiote_input_configure(abs_pin, NULL, &trigger_config, NULL); + err = nrfx_gpiote_input_configure(&cfg->gpiote, abs_pin, &input_pin_config); if (err != NRFX_SUCCESS) { return -EINVAL; } - nrfx_gpiote_trigger_enable(abs_pin, true); + nrfx_gpiote_trigger_enable(&cfg->gpiote, abs_pin, true); return 0; } @@ -367,26 +385,31 @@ static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin, } #endif /* CONFIG_GPIO_NRFX_INTERRUPT */ -#define GPIOTE_NODE DT_INST(0, nordic_nrf_gpiote) +#define GPIOTE_IRQ_HANDLER_CONNECT(node_id) \ + 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_init(const struct device *port) { + const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); nrfx_err_t err; - if (nrfx_gpiote_is_init()) { + if (!has_gpiote(cfg)) { + return 0; + } + + if (nrfx_gpiote_init_check(&cfg->gpiote)) { return 0; } - err = nrfx_gpiote_init(0/*not used*/); + err = nrfx_gpiote_init(&cfg->gpiote, 0 /*not used*/); if (err != NRFX_SUCCESS) { return -EIO; } #ifdef CONFIG_GPIO_NRFX_INTERRUPT - nrfx_gpiote_global_callback_set(nrfx_gpio_handler, NULL); - - IRQ_CONNECT(DT_IRQN(GPIOTE_NODE), DT_IRQ(GPIOTE_NODE, priority), - nrfx_isr, nrfx_gpiote_irq_handler, 0); + nrfx_gpiote_global_callback_set(&cfg->gpiote, nrfx_gpio_handler, NULL); + DT_FOREACH_STATUS_OKAY(nordic_nrf_gpiote, GPIOTE_IRQ_HANDLER_CONNECT); #endif /* CONFIG_GPIO_NRFX_INTERRUPT */ return 0; @@ -408,12 +431,27 @@ static const struct gpio_driver_api gpio_nrfx_drv_api_funcs = { #endif }; +#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance) +#define GPIOTE_INST(id) DT_PROP(GPIOTE_PHANDLE(id), instance) + +#define GPIOTE_INSTANCE(id) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(id, gpiote_instance), \ + (NRFX_GPIOTE_INSTANCE(GPIOTE_INST(id))), \ + ({ .p_reg = NULL })) + /* Device instantiation is done with node labels because 'port_num' is * the peripheral number by SoC numbering. We therefore cannot use * DT_INST APIs here without wider changes. */ +#define GPIOTE_CHECK(id) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(id, gpiote_instance), \ + (BUILD_ASSERT(DT_NODE_HAS_STATUS(GPIOTE_PHANDLE(id), okay), \ + "Please enable GPIOTE instance for used GPIO port!")), \ + ()) + #define GPIO_NRF_DEVICE(id) \ + GPIOTE_CHECK(id); \ static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \ .common = { \ .port_pin_mask = \ @@ -421,7 +459,8 @@ static const struct gpio_driver_api gpio_nrfx_drv_api_funcs = { }, \ .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \ .port_num = DT_INST_PROP(id, port), \ - .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0) \ + .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \ + .gpiote = GPIOTE_INSTANCE(id), \ }; \ \ static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \ diff --git a/drivers/gpio/gpio_stm32.c b/drivers/gpio/gpio_stm32.c index 877dbb4882cf3c2..fe6d98d7a35d741 100644 --- a/drivers/gpio/gpio_stm32.c +++ b/drivers/gpio/gpio_stm32.c @@ -719,7 +719,9 @@ static int gpio_stm32_init(const struct device *dev) return ret; } - pm_device_init_suspended(dev); + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + pm_device_init_suspended(dev); + } (void)pm_device_runtime_enable(dev); return 0; diff --git a/drivers/hwinfo/Kconfig b/drivers/hwinfo/Kconfig index f293ab60b7f18e3..84afbefd84feb1a 100644 --- a/drivers/hwinfo/Kconfig +++ b/drivers/hwinfo/Kconfig @@ -188,7 +188,7 @@ config HWINFO_GECKO config HWINFO_ANDES bool "Andes system ID" default y - depends on SOC_SERIES_RISCV_ANDES_V5 + depends on SOC_FAMILY_ANDES_V5 help Enable Andes hwinfo driver diff --git a/drivers/i2c/i2c_dw.c b/drivers/i2c/i2c_dw.c index 3dd006fb5aed4e0..443bee9059c06d2 100644 --- a/drivers/i2c/i2c_dw.c +++ b/drivers/i2c/i2c_dw.c @@ -201,10 +201,10 @@ static inline void i2c_dw_data_ask(const struct device *dev) { struct i2c_dw_dev_config * const dw = dev->data; uint32_t data; - uint8_t tx_empty; - int8_t rx_empty; - uint8_t cnt; - uint8_t rx_buffer_depth, tx_buffer_depth; + int tx_empty; + int rx_empty; + int cnt; + int rx_buffer_depth, tx_buffer_depth; union ic_comp_param_1_register ic_comp_param_1; uint32_t reg_base = get_regs(dev); diff --git a/drivers/i2c/i2c_mcux_lpi2c.c b/drivers/i2c/i2c_mcux_lpi2c.c index cc6d7954b588041..166603593122e20 100644 --- a/drivers/i2c/i2c_mcux_lpi2c.c +++ b/drivers/i2c/i2c_mcux_lpi2c.c @@ -32,8 +32,13 @@ LOG_MODULE_REGISTER(mcux_lpi2c); */ #define SCAN_DELAY_US(baudrate) (12 * USEC_PER_SEC / baudrate) +/* Required by DEVICE_MMIO_NAMED_* macros */ +#define DEV_CFG(_dev) \ + ((const struct mcux_lpi2c_config *)(_dev)->config) +#define DEV_DATA(_dev) ((struct mcux_lpi2c_data *)(_dev)->data) + struct mcux_lpi2c_config { - LPI2C_Type *base; + DEVICE_MMIO_NAMED_ROM(reg_base); const struct device *clock_dev; clock_control_subsys_t clock_subsys; void (*irq_config_func)(const struct device *dev); @@ -47,6 +52,7 @@ struct mcux_lpi2c_config { }; struct mcux_lpi2c_data { + DEVICE_MMIO_NAMED_RAM(reg_base); lpi2c_master_handle_t handle; struct k_sem lock; struct k_sem device_sync_sem; @@ -66,7 +72,7 @@ static int mcux_lpi2c_configure(const struct device *dev, { const struct mcux_lpi2c_config *config = dev->config; struct mcux_lpi2c_data *data = dev->data; - LPI2C_Type *base = config->base; + LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); uint32_t clock_freq; uint32_t baudrate; int ret; @@ -138,11 +144,11 @@ static uint32_t mcux_lpi2c_convert_flags(int msg_flags) } static int mcux_lpi2c_transfer(const struct device *dev, struct i2c_msg *msgs, - uint8_t num_msgs, uint16_t addr) + uint8_t num_msgs, uint16_t addr) { const struct mcux_lpi2c_config *config = dev->config; struct mcux_lpi2c_data *data = dev->data; - LPI2C_Type *base = config->base; + LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); lpi2c_master_transfer_t transfer; status_t status; int ret = 0; @@ -304,8 +310,8 @@ static int mcux_lpi2c_recover_bus(const struct device *dev) #ifdef CONFIG_I2C_TARGET static void mcux_lpi2c_slave_irq_handler(const struct device *dev) { - const struct mcux_lpi2c_config *config = dev->config; struct mcux_lpi2c_data *data = dev->data; + LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks; int ret; uint32_t flags; @@ -319,11 +325,11 @@ static void mcux_lpi2c_slave_irq_handler(const struct device *dev) * every byte. For these reason, we handle the LPI2C IRQ * directly. */ - flags = LPI2C_SlaveGetStatusFlags(config->base); + flags = LPI2C_SlaveGetStatusFlags(base); if (flags & kLPI2C_SlaveAddressValidFlag) { /* Read Slave address to clear flag */ - LPI2C_SlaveGetReceivedAddress(config->base); + LPI2C_SlaveGetReceivedAddress(base); data->first_tx = true; /* Reset to sending ACK, in case we NAK'ed before */ data->send_ack = true; @@ -331,7 +337,7 @@ static void mcux_lpi2c_slave_irq_handler(const struct device *dev) if (flags & kLPI2C_SlaveRxReadyFlag) { /* RX data is available, read it and issue callback */ - i2c_data = (uint8_t)config->base->SRDR; + i2c_data = (uint8_t)base->SRDR; if (data->first_tx) { data->first_tx = false; if (target_cb->write_requested) { @@ -365,7 +371,7 @@ static void mcux_lpi2c_slave_irq_handler(const struct device *dev) data->read_active = false; } else { /* Send I2C data */ - config->base->STDR = i2c_data; + base->STDR = i2c_data; } } } else if (data->read_active) { @@ -377,33 +383,34 @@ static void mcux_lpi2c_slave_irq_handler(const struct device *dev) data->read_active = false; } else { /* Send I2C data */ - config->base->STDR = i2c_data; + base->STDR = i2c_data; } } } } if (flags & kLPI2C_SlaveStopDetectFlag) { - LPI2C_SlaveClearStatusFlags(config->base, flags); + LPI2C_SlaveClearStatusFlags(base, flags); if (target_cb->stop) { target_cb->stop(data->target_cfg); } } if (flags & kLPI2C_SlaveTransmitAckFlag) { - LPI2C_SlaveTransmitAck(config->base, data->send_ack); + LPI2C_SlaveTransmitAck(base, data->send_ack); } } static int mcux_lpi2c_target_register(const struct device *dev, - struct i2c_target_config *target_config) + struct i2c_target_config *target_config) { const struct mcux_lpi2c_config *config = dev->config; struct mcux_lpi2c_data *data = dev->data; + LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); lpi2c_slave_config_t slave_config; uint32_t clock_freq; - LPI2C_MasterDeinit(config->base); + LPI2C_MasterDeinit(base); /* Get the clock frequency */ if (clock_control_get_rate(config->clock_dev, config->clock_subsys, @@ -430,11 +437,11 @@ static int mcux_lpi2c_target_register(const struct device *dev, * this behavior may cause issues with some I2C controllers. */ slave_config.sclStall.enableAck = true; - LPI2C_SlaveInit(config->base, &slave_config, clock_freq); + LPI2C_SlaveInit(base, &slave_config, clock_freq); /* Clear all flags. */ - LPI2C_SlaveClearStatusFlags(config->base, (uint32_t)kLPI2C_SlaveClearFlags); + LPI2C_SlaveClearStatusFlags(base, (uint32_t)kLPI2C_SlaveClearFlags); /* Enable interrupt */ - LPI2C_SlaveEnableInterrupts(config->base, + LPI2C_SlaveEnableInterrupts(base, (kLPI2C_SlaveTxReadyFlag | kLPI2C_SlaveRxReadyFlag | kLPI2C_SlaveStopDetectFlag | @@ -446,8 +453,8 @@ static int mcux_lpi2c_target_register(const struct device *dev, static int mcux_lpi2c_target_unregister(const struct device *dev, struct i2c_target_config *target_config) { - const struct mcux_lpi2c_config *config = dev->config; struct mcux_lpi2c_data *data = dev->data; + LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); if (!data->target_attached) { return -EINVAL; @@ -456,7 +463,7 @@ static int mcux_lpi2c_target_unregister(const struct device *dev, data->target_cfg = NULL; data->target_attached = false; - LPI2C_SlaveDeinit(config->base); + LPI2C_SlaveDeinit(base); return 0; } @@ -464,9 +471,8 @@ static int mcux_lpi2c_target_unregister(const struct device *dev, static void mcux_lpi2c_isr(const struct device *dev) { - const struct mcux_lpi2c_config *config = dev->config; struct mcux_lpi2c_data *data = dev->data; - LPI2C_Type *base = config->base; + LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); #ifdef CONFIG_I2C_TARGET if (data->target_attached) { @@ -481,11 +487,15 @@ static int mcux_lpi2c_init(const struct device *dev) { const struct mcux_lpi2c_config *config = dev->config; struct mcux_lpi2c_data *data = dev->data; - LPI2C_Type *base = config->base; + LPI2C_Type *base; uint32_t clock_freq, bitrate_cfg; lpi2c_master_config_t master_config; int error; + DEVICE_MMIO_NAMED_MAP(dev, reg_base, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + + base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); + k_sem_init(&data->lock, 1, 1); k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT); @@ -549,7 +559,7 @@ static const struct i2c_driver_api mcux_lpi2c_driver_api = { static void mcux_lpi2c_config_func_##n(const struct device *dev); \ \ static const struct mcux_lpi2c_config mcux_lpi2c_config_##n = { \ - .base = (LPI2C_Type *)DT_INST_REG_ADDR(n), \ + DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ .clock_subsys = \ (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\ @@ -566,17 +576,17 @@ static const struct i2c_driver_api mcux_lpi2c_driver_api = { static struct mcux_lpi2c_data mcux_lpi2c_data_##n; \ \ I2C_DEVICE_DT_INST_DEFINE(n, mcux_lpi2c_init, NULL, \ - &mcux_lpi2c_data_##n, \ - &mcux_lpi2c_config_##n, POST_KERNEL, \ - CONFIG_I2C_INIT_PRIORITY, \ - &mcux_lpi2c_driver_api); \ + &mcux_lpi2c_data_##n, \ + &mcux_lpi2c_config_##n, POST_KERNEL, \ + CONFIG_I2C_INIT_PRIORITY, \ + &mcux_lpi2c_driver_api); \ \ static void mcux_lpi2c_config_func_##n(const struct device *dev) \ { \ IRQ_CONNECT(DT_INST_IRQN(n), \ - DT_INST_IRQ(n, priority), \ - mcux_lpi2c_isr, \ - DEVICE_DT_INST_GET(n), 0); \ + DT_INST_IRQ(n, priority), \ + mcux_lpi2c_isr, \ + DEVICE_DT_INST_GET(n), 0); \ \ irq_enable(DT_INST_IRQN(n)); \ } diff --git a/drivers/i2s/Kconfig.stm32 b/drivers/i2s/Kconfig.stm32 index 8ef499ce7c96860..26a5e82754430ff 100644 --- a/drivers/i2s/Kconfig.stm32 +++ b/drivers/i2s/Kconfig.stm32 @@ -10,7 +10,7 @@ menuconfig I2S_STM32 select DMA help Enable I2S support on the STM32 family of processors. - (Tested on the STM32F4 series) + (Tested on the STM32F4 & STM32H7 series) if I2S_STM32 diff --git a/drivers/i2s/i2s_ll_stm32.c b/drivers/i2s/i2s_ll_stm32.c index 7ff2d2c3b6ec21b..168e8097dd0f7df 100644 --- a/drivers/i2s/i2s_ll_stm32.c +++ b/drivers/i2s/i2s_ll_stm32.c @@ -22,11 +22,7 @@ #include LOG_MODULE_REGISTER(i2s_ll_stm32); -/* FIXME change to - * #if __DCACHE_PRESENT == 1 - * when cache support is added - */ -#if 0 +#if __DCACHE_PRESENT == 1 #define DCACHE_INVALIDATE(addr, size) \ SCB_InvalidateDCache_by_Addr((uint32_t *)addr, size) #define DCACHE_CLEAN(addr, size) \ @@ -187,6 +183,9 @@ static int i2s_stm32_configure(const struct device *dev, enum i2s_dir dir, int ret; if (dir == I2S_DIR_RX) { +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + return -ENOSYS; +#endif stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; @@ -549,7 +548,11 @@ static void dma_rx_callback(const struct device *dma_dev, void *arg, ret = reload_dma(stream->dev_dma, stream->dma_channel, &stream->dma_cfg, +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + (void *)LL_SPI_DMA_GetRxRegAddr(cfg->i2s), +#else (void *)LL_SPI_DMA_GetRegAddr(cfg->i2s), +#endif stream->mem_block, stream->cfg.block_size); if (ret < 0) { @@ -634,7 +637,11 @@ static void dma_tx_callback(const struct device *dma_dev, void *arg, ret = reload_dma(stream->dev_dma, stream->dma_channel, &stream->dma_cfg, stream->mem_block, +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + (void *)LL_SPI_DMA_GetTxRegAddr(cfg->i2s), +#else (void *)LL_SPI_DMA_GetRegAddr(cfg->i2s), +#endif stream->cfg.block_size); if (ret < 0) { LOG_DBG("Failed to start TX DMA transfer: %d", ret); @@ -649,6 +656,7 @@ static void dma_tx_callback(const struct device *dma_dev, void *arg, static uint32_t i2s_stm32_irq_count; static uint32_t i2s_stm32_irq_ovr_count; +static uint32_t i2s_stm32_irq_udr_count; static void i2s_stm32_isr(const struct device *dev) { @@ -665,6 +673,12 @@ static void i2s_stm32_isr(const struct device *dev) LL_I2S_ClearFlag_OVR(cfg->i2s); } + /* NOTE: UDR error must be explicitly cleared on STM32H7 */ + if (LL_I2S_IsActiveFlag_UDR(cfg->i2s)) { + i2s_stm32_irq_udr_count++; + LL_I2S_ClearFlag_UDR(cfg->i2s); + } + i2s_stm32_irq_count++; } @@ -736,7 +750,11 @@ static int rx_stream_start(struct stream *stream, const struct device *dev) ret = start_dma(stream->dev_dma, stream->dma_channel, &stream->dma_cfg, +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + (void *)LL_SPI_DMA_GetRxRegAddr(cfg->i2s), +#else (void *)LL_SPI_DMA_GetRegAddr(cfg->i2s), +#endif stream->src_addr_increment, stream->mem_block, stream->dst_addr_increment, stream->fifo_threshold, stream->cfg.block_size); @@ -747,8 +765,17 @@ static int rx_stream_start(struct stream *stream, const struct device *dev) LL_I2S_EnableDMAReq_RX(cfg->i2s); +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + LL_I2S_EnableIT_OVR(cfg->i2s); + LL_I2S_EnableIT_UDR(cfg->i2s); + LL_I2S_EnableIT_FRE(cfg->i2s); + LL_I2S_Enable(cfg->i2s); + LL_SPI_StartMasterTransfer(cfg->i2s); +#else LL_I2S_EnableIT_ERR(cfg->i2s); LL_I2S_Enable(cfg->i2s); +#endif + return 0; } @@ -781,7 +808,11 @@ static int tx_stream_start(struct stream *stream, const struct device *dev) ret = start_dma(stream->dev_dma, stream->dma_channel, &stream->dma_cfg, stream->mem_block, stream->src_addr_increment, +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + (void *)LL_SPI_DMA_GetTxRegAddr(cfg->i2s), +#else (void *)LL_SPI_DMA_GetRegAddr(cfg->i2s), +#endif stream->dst_addr_increment, stream->fifo_threshold, stream->cfg.block_size); if (ret < 0) { @@ -791,8 +822,17 @@ static int tx_stream_start(struct stream *stream, const struct device *dev) LL_I2S_EnableDMAReq_TX(cfg->i2s); +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + LL_I2S_EnableIT_OVR(cfg->i2s); + LL_I2S_EnableIT_UDR(cfg->i2s); + LL_I2S_EnableIT_FRE(cfg->i2s); + + LL_I2S_Enable(cfg->i2s); + LL_SPI_StartMasterTransfer(cfg->i2s); +#else LL_I2S_EnableIT_ERR(cfg->i2s); LL_I2S_Enable(cfg->i2s); +#endif return 0; } @@ -802,7 +842,13 @@ static void rx_stream_disable(struct stream *stream, const struct device *dev) const struct i2s_stm32_cfg *cfg = dev->config; LL_I2S_DisableDMAReq_RX(cfg->i2s); +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + LL_I2S_DisableIT_OVR(cfg->i2s); + LL_I2S_DisableIT_UDR(cfg->i2s); + LL_I2S_DisableIT_FRE(cfg->i2s); +#else LL_I2S_DisableIT_ERR(cfg->i2s); +#endif dma_stop(stream->dev_dma, stream->dma_channel); if (stream->mem_block != NULL) { @@ -820,7 +866,13 @@ static void tx_stream_disable(struct stream *stream, const struct device *dev) const struct i2s_stm32_cfg *cfg = dev->config; LL_I2S_DisableDMAReq_TX(cfg->i2s); +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + LL_I2S_DisableIT_OVR(cfg->i2s); + LL_I2S_DisableIT_UDR(cfg->i2s); + LL_I2S_DisableIT_FRE(cfg->i2s); +#else LL_I2S_DisableIT_ERR(cfg->i2s); +#endif dma_stop(stream->dev_dma, stream->dma_channel); if (stream->mem_block != NULL) { diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig index feccd4a60012aa4..d692024b096dc44 100644 --- a/drivers/ieee802154/Kconfig +++ b/drivers/ieee802154/Kconfig @@ -98,11 +98,6 @@ config IEEE802154_CSL_DEBUG help Enable support for CSL debugging by avoiding sleep state in favor of receive state. -config IEEE802154_SELECTIVE_TXPOWER - bool "Support selective TX power setting" - help - Enable support for selectively setting TX power for every transmission request. - module = IEEE802154_DRIVER module-str = IEEE 802.15.4 driver module-help = Sets log level for IEEE 802.15.4 Device Drivers. diff --git a/drivers/ieee802154/ieee802154_b91.c b/drivers/ieee802154/ieee802154_b91.c index 0557c53394423a0..e19356a272a3f98 100644 --- a/drivers/ieee802154/ieee802154_b91.c +++ b/drivers/ieee802154/ieee802154_b91.c @@ -617,7 +617,7 @@ static int b91_attr_get(const struct device *dev, enum ieee802154_attr attr, } /* IEEE802154 driver APIs structure */ -static struct ieee802154_radio_api b91_radio_api = { +static const struct ieee802154_radio_api b91_radio_api = { .iface_api.init = b91_iface_init, .get_capabilities = b91_get_capabilities, .cca = b91_cca, diff --git a/drivers/ieee802154/ieee802154_cc1200.c b/drivers/ieee802154/ieee802154_cc1200.c index e5f8ea3667021b9..7bc3aa3ed12c93f 100644 --- a/drivers/ieee802154/ieee802154_cc1200.c +++ b/drivers/ieee802154/ieee802154_cc1200.c @@ -813,7 +813,7 @@ static const struct cc1200_config cc1200_config = { static struct cc1200_context cc1200_context_data; -static struct ieee802154_radio_api cc1200_radio_api = { +static const struct ieee802154_radio_api cc1200_radio_api = { .iface_api.init = cc1200_iface_init, .get_capabilities = cc1200_get_capabilities, diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c index 5d5a53ed08e74cc..263b98d2823d79f 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c @@ -570,7 +570,7 @@ static void ieee802154_cc13xx_cc26xx_iface_init(struct net_if *iface) ieee802154_init(iface); } -static struct ieee802154_radio_api ieee802154_cc13xx_cc26xx_radio_api = { +static const struct ieee802154_radio_api ieee802154_cc13xx_cc26xx_radio_api = { .iface_api.init = ieee802154_cc13xx_cc26xx_iface_init, .get_capabilities = ieee802154_cc13xx_cc26xx_get_capabilities, diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c index ea626908d168db8..dbaa02ff9eb2845 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c @@ -909,7 +909,7 @@ static void ieee802154_cc13xx_cc26xx_subg_iface_init(struct net_if *iface) ieee802154_init(iface); } -static struct ieee802154_radio_api +static const struct ieee802154_radio_api ieee802154_cc13xx_cc26xx_subg_radio_api = { .iface_api.init = ieee802154_cc13xx_cc26xx_subg_iface_init, diff --git a/drivers/ieee802154/ieee802154_cc2520.c b/drivers/ieee802154/ieee802154_cc2520.c index cf7c10916610adb..1f86d20d02f0b1c 100644 --- a/drivers/ieee802154/ieee802154_cc2520.c +++ b/drivers/ieee802154/ieee802154_cc2520.c @@ -1057,7 +1057,7 @@ static const struct cc2520_config cc2520_config = { static struct cc2520_context cc2520_context_data; -static struct ieee802154_radio_api cc2520_radio_api = { +static const struct ieee802154_radio_api cc2520_radio_api = { .iface_api.init = cc2520_iface_init, .get_capabilities = cc2520_get_capabilities, diff --git a/drivers/ieee802154/ieee802154_dw1000.c b/drivers/ieee802154/ieee802154_dw1000.c index d20df48896641db..13d5e047544fd7f 100644 --- a/drivers/ieee802154/ieee802154_dw1000.c +++ b/drivers/ieee802154/ieee802154_dw1000.c @@ -1659,7 +1659,7 @@ static void dwt_iface_api_init(struct net_if *iface) LOG_INF("Iface initialized"); } -static struct ieee802154_radio_api dwt_radio_api = { +static const struct ieee802154_radio_api dwt_radio_api = { .iface_api.init = dwt_iface_api_init, .get_capabilities = dwt_get_capabilities, diff --git a/drivers/ieee802154/ieee802154_kw41z.c b/drivers/ieee802154/ieee802154_kw41z.c index aee802ad6ff1a3d..40064c6df7b5959 100644 --- a/drivers/ieee802154/ieee802154_kw41z.c +++ b/drivers/ieee802154/ieee802154_kw41z.c @@ -1091,7 +1091,7 @@ static int kw41z_attr_get(const struct device *dev, enum ieee802154_attr attr, &drv_attr.phy_supported_channels, value); } -static struct ieee802154_radio_api kw41z_radio_api = { +static const struct ieee802154_radio_api kw41z_radio_api = { .iface_api.init = kw41z_iface_init, .get_capabilities = kw41z_get_capabilities, diff --git a/drivers/ieee802154/ieee802154_mcr20a.c b/drivers/ieee802154/ieee802154_mcr20a.c index 6a1e5a99727b24e..2e6ed14286116d4 100644 --- a/drivers/ieee802154/ieee802154_mcr20a.c +++ b/drivers/ieee802154/ieee802154_mcr20a.c @@ -1452,7 +1452,7 @@ static const struct mcr20a_config mcr20a_config = { static struct mcr20a_context mcr20a_context_data; -static struct ieee802154_radio_api mcr20a_radio_api = { +static const struct ieee802154_radio_api mcr20a_radio_api = { .iface_api.init = mcr20a_iface_init, .get_capabilities = mcr20a_get_capabilities, diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index df01f530abffbc9..108bcd2e14acdf4 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -236,6 +236,7 @@ static void nrf5_get_capabilities_at_boot(void) ((caps & NRF_802154_CAPABILITY_DELAYED_TX) ? IEEE802154_HW_TXTIME : 0UL) | ((caps & NRF_802154_CAPABILITY_DELAYED_RX) ? IEEE802154_HW_RXTIME : 0UL) | IEEE802154_HW_SLEEP_TO_TX | + IEEE802154_RX_ON_WHEN_IDLE | ((caps & NRF_802154_CAPABILITY_SECURITY) ? IEEE802154_HW_TX_SEC : 0UL) #if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) | IEEE802154_OPENTHREAD_HW_MULTIPLE_CCA @@ -254,6 +255,8 @@ static int nrf5_cca(const struct device *dev) { struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev); + nrf_802154_channel_set(nrf5_data.channel); + if (!nrf_802154_cca()) { LOG_DBG("CCA failed"); return -EBUSY; @@ -279,7 +282,7 @@ static int nrf5_set_channel(const struct device *dev, uint16_t channel) return channel < 11 ? -ENOTSUP : -EINVAL; } - nrf_802154_channel_set(channel); + nrf5_data.channel = channel; return 0; } @@ -292,6 +295,8 @@ static int nrf5_energy_scan_start(const struct device *dev, ARG_UNUSED(dev); + nrf_802154_channel_set(nrf5_data.channel); + if (nrf5_data.energy_scan_done == NULL) { nrf5_data.energy_scan_done = done_cb; @@ -375,7 +380,7 @@ static int nrf5_set_txpower(const struct device *dev, int16_t dbm) LOG_DBG("%d", dbm); - nrf_802154_tx_power_set(dbm); + nrf5_data.txpwr = dbm; return 0; } @@ -454,10 +459,12 @@ static bool nrf5_tx_immediate(struct net_pkt *pkt, uint8_t *payload, bool cca) }, .cca = cca, .tx_power = { - .use_metadata_value = IS_ENABLED(CONFIG_IEEE802154_SELECTIVE_TXPOWER), -#if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER) - .power = net_pkt_ieee802154_txpwr(pkt), -#endif + .use_metadata_value = true, + .power = nrf5_data.txpwr, + }, + .tx_channel = { + .use_metadata_value = true, + .channel = nrf5_data.channel, }, }; @@ -473,10 +480,12 @@ static bool nrf5_tx_csma_ca(struct net_pkt *pkt, uint8_t *payload) .dynamic_data_is_set = net_pkt_ieee802154_mac_hdr_rdy(pkt), }, .tx_power = { - .use_metadata_value = IS_ENABLED(CONFIG_IEEE802154_SELECTIVE_TXPOWER), -#if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER) - .power = net_pkt_ieee802154_txpwr(pkt), -#endif + .use_metadata_value = true, + .power = nrf5_data.txpwr, + }, + .tx_channel = { + .use_metadata_value = true, + .channel = nrf5_data.channel, }, }; @@ -517,12 +526,10 @@ static bool nrf5_tx_at(struct nrf5_802154_data *nrf5_radio, struct net_pkt *pkt, .dynamic_data_is_set = net_pkt_ieee802154_mac_hdr_rdy(pkt), }, .cca = cca, - .channel = nrf_802154_channel_get(), + .channel = nrf5_data.channel, .tx_power = { - .use_metadata_value = IS_ENABLED(CONFIG_IEEE802154_SELECTIVE_TXPOWER), -#if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER) - .power = net_pkt_ieee802154_txpwr(pkt), -#endif + .use_metadata_value = true, + .power = nrf5_data.txpwr, }, #if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) .extra_cca_attempts = max_extra_cca_attempts, @@ -660,6 +667,9 @@ static int nrf5_start(const struct device *dev) { ARG_UNUSED(dev); + nrf_802154_tx_power_set(nrf5_data.txpwr); + nrf_802154_channel_set(nrf5_data.channel); + if (!nrf_802154_receive()) { LOG_ERR("Failed to enter receive state"); return -EIO; @@ -702,6 +712,9 @@ static int nrf5_continuous_carrier(const struct device *dev) { ARG_UNUSED(dev); + nrf_802154_tx_power_set(nrf5_data.txpwr); + nrf_802154_channel_set(nrf5_data.channel); + if (!nrf_802154_continuous_carrier()) { LOG_ERR("Failed to enter continuous carrier state"); return -EIO; @@ -975,6 +988,10 @@ static int nrf5_configure(const struct device *dev, break; #endif /* CONFIG_IEEE802154_NRF5_MULTIPLE_CCA */ + case IEEE802154_CONFIG_RX_ON_WHEN_IDLE: + nrf_802154_rx_on_when_idle_set(config->rx_on_when_idle); + break; + default: return -EINVAL; } @@ -1052,20 +1069,8 @@ void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) const struct device *dev = nrf5_get_device(); #if defined(CONFIG_IEEE802154_CSL_ENDPOINT) - if (id == DRX_SLOT_RX) { - __ASSERT_NO_MSG(nrf5_data.event_handler); -#if !defined(CONFIG_IEEE802154_CSL_DEBUG) - /* When CSL debug option is used we intentionally avoid notifying the higher layer - * about the finalization of a DRX slot, so that the radio stays in receive state - * for receiving "out of slot" frames. - * As a side effect, regular failure notifications would be reported with the - * incorrect ID. - */ - nrf5_data.event_handler(dev, IEEE802154_EVENT_RX_OFF, NULL); -#endif - if (error == NRF_802154_RX_ERROR_DELAYED_TIMEOUT) { - return; - } + if (id == DRX_SLOT_RX && error == NRF_802154_RX_ERROR_DELAYED_TIMEOUT) { + return; } #else ARG_UNUSED(id); @@ -1194,7 +1199,7 @@ static const struct nrf5_802154_config nrf5_radio_cfg = { .irq_config_func = nrf5_irq_config, }; -static struct ieee802154_radio_api nrf5_radio_api = { +static const struct ieee802154_radio_api nrf5_radio_api = { .iface_api.init = nrf5_iface_init, .get_capabilities = nrf5_get_capabilities, diff --git a/drivers/ieee802154/ieee802154_nrf5.h b/drivers/ieee802154/ieee802154_nrf5.h index 9115fe0bdaeef42..b9f46dff307e991 100644 --- a/drivers/ieee802154/ieee802154_nrf5.h +++ b/drivers/ieee802154/ieee802154_nrf5.h @@ -97,6 +97,12 @@ struct nrf5_802154_data { uint8_t max_extra_cca_attempts; #endif + /* The TX power in dBm. */ + int8_t txpwr; + + /* The radio channel. */ + uint8_t channel; + #if defined(CONFIG_NRF_802154_SER_HOST) && defined(CONFIG_IEEE802154_CSL_ENDPOINT) /* The last configured value of CSL period in units of 10 symbols. */ uint32_t csl_period; diff --git a/drivers/ieee802154/ieee802154_rf2xx.c b/drivers/ieee802154/ieee802154_rf2xx.c index ac7f13580d0a50b..4d7c188ce675bc3 100644 --- a/drivers/ieee802154/ieee802154_rf2xx.c +++ b/drivers/ieee802154/ieee802154_rf2xx.c @@ -1084,7 +1084,7 @@ static void rf2xx_iface_init(struct net_if *iface) ieee802154_init(iface); } -static struct ieee802154_radio_api rf2xx_radio_api = { +static const struct ieee802154_radio_api rf2xx_radio_api = { .iface_api.init = rf2xx_iface_init, .get_capabilities = rf2xx_get_capabilities, diff --git a/drivers/ieee802154/ieee802154_uart_pipe.c b/drivers/ieee802154/ieee802154_uart_pipe.c index cdb420d97471ecd..72bcf5b8ebf6c03 100644 --- a/drivers/ieee802154/ieee802154_uart_pipe.c +++ b/drivers/ieee802154/ieee802154_uart_pipe.c @@ -392,7 +392,7 @@ static void upipe_iface_init(struct net_if *iface) static struct upipe_context upipe_context_data; -static struct ieee802154_radio_api upipe_radio_api = { +static const struct ieee802154_radio_api upipe_radio_api = { .iface_api.init = upipe_iface_init, .get_capabilities = upipe_get_capabilities, diff --git a/drivers/input/CMakeLists.txt b/drivers/input/CMakeLists.txt index 012bb08b2839718..9aeb9198b310a64 100644 --- a/drivers/input/CMakeLists.txt +++ b/drivers/input/CMakeLists.txt @@ -4,6 +4,8 @@ zephyr_library() zephyr_library_property(ALLOW_EMPTY TRUE) # zephyr-keep-sorted-start +zephyr_library_sources_ifdef(CONFIG_INPUT_ANALOG_AXIS input_analog_axis.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_ANALOG_AXIS_SETTINGS input_analog_axis_settings.c) zephyr_library_sources_ifdef(CONFIG_INPUT_CAP1203 input_cap1203.c) zephyr_library_sources_ifdef(CONFIG_INPUT_CST816S input_cst816s.c) zephyr_library_sources_ifdef(CONFIG_INPUT_ESP32_TOUCH_SENSOR input_esp32_touch_sensor.c) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 8aa5471e57141de..41c93241f2aa036 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -6,6 +6,7 @@ if INPUT menu "Input drivers" # zephyr-keep-sorted-start +source "drivers/input/Kconfig.analog_axis" source "drivers/input/Kconfig.cap1203" source "drivers/input/Kconfig.cst816s" source "drivers/input/Kconfig.esp32" diff --git a/drivers/input/Kconfig.analog_axis b/drivers/input/Kconfig.analog_axis new file mode 100644 index 000000000000000..472b611acea8e22 --- /dev/null +++ b/drivers/input/Kconfig.analog_axis @@ -0,0 +1,43 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +config INPUT_ANALOG_AXIS + bool "ADC based analog axis input driver" + default y + depends on DT_HAS_ANALOG_AXIS_ENABLED + depends on ADC + depends on MULTITHREADING + help + ADC based analog axis input driver + +if INPUT_ANALOG_AXIS + +config INPUT_ANALOG_AXIS_THREAD_STACK_SIZE + int "Stack size for the analog axis thread" + default 762 + help + Size of the stack used for the analog axis thread. + +config INPUT_ANALOG_AXIS_THREAD_PRIORITY + int "Priority for the analog axis thread" + default 0 + help + Priority level of the analog axis thread. + +config INPUT_ANALOG_AXIS_SETTINGS + bool "Analog axis settings support" + default y + depends on SETTINGS + help + Settings support for the analog axis driver, exposes a + analog_axis_calibration_save() function to save the calibration into + settings and load them automatically on startup. + +config INPUT_ANALOG_AXIS_SETTINGS_MAX_AXES + int "Maximum number of axes supported in the settings." + default 8 + help + Maximum number of axes that can have calibration value saved in + settings. + +endif diff --git a/drivers/input/Kconfig.evdev b/drivers/input/Kconfig.evdev index ed2ac16d8120609..568797800f38528 100644 --- a/drivers/input/Kconfig.evdev +++ b/drivers/input/Kconfig.evdev @@ -6,6 +6,7 @@ config NATIVE_LINUX_EVDEV default y depends on DT_HAS_ZEPHYR_NATIVE_LINUX_EVDEV_ENABLED depends on ARCH_POSIX + depends on MULTITHREADING help Enable reading input from a Linux evdev device, requires specifying an evdev device path in the --evdev command line argument. diff --git a/drivers/input/Kconfig.it8xxx2 b/drivers/input/Kconfig.it8xxx2 index 6e729b27c3a927d..0c59b3425342fd3 100644 --- a/drivers/input/Kconfig.it8xxx2 +++ b/drivers/input/Kconfig.it8xxx2 @@ -6,6 +6,5 @@ config INPUT_ITE_IT8XXX2_KBD default y depends on DT_HAS_ITE_IT8XXX2_KBD_ENABLED select INPUT_KBD_MATRIX - select MULTITHREADING help This option enables the ITE keyboard scan driver. diff --git a/drivers/input/Kconfig.kbd_matrix b/drivers/input/Kconfig.kbd_matrix index cbacb9ca4c03d33..4532b270f9c0353 100644 --- a/drivers/input/Kconfig.kbd_matrix +++ b/drivers/input/Kconfig.kbd_matrix @@ -3,6 +3,7 @@ config INPUT_KBD_MATRIX bool + depends on MULTITHREADING help Enable library used for keyboard matrix drivers. @@ -30,9 +31,9 @@ config INPUT_KBD_MATRIX_16_BIT_ROW config INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC bool "Allow runtime changes to the actual key mask" help - If enabled, the actual key mask data is stored in RAM, and a - input_kbd_matrix_actual_key_mask_set() function is available to - change the content at runtime. + If enabled, the actual-key-mask devicetree property data is stored in + RAM, and a input_kbd_matrix_actual_key_mask_set() function is + available to change the content at runtime. config INPUT_SHELL_KBD_MATRIX_STATE bool "Input kbd_matrix_state shell command" diff --git a/drivers/input/Kconfig.npcx b/drivers/input/Kconfig.npcx index ef380b0ca4be478..07c2e301944bdb2 100644 --- a/drivers/input/Kconfig.npcx +++ b/drivers/input/Kconfig.npcx @@ -8,7 +8,6 @@ config INPUT_NPCX_KBD default y depends on DT_HAS_NUVOTON_NPCX_KBD_ENABLED select INPUT_KBD_MATRIX - select MULTITHREADING help This option enables the keyboard scan driver for NPCX family of processors. diff --git a/drivers/input/input_analog_axis.c b/drivers/input/input_analog_axis.c new file mode 100644 index 000000000000000..ace693ddf585c39 --- /dev/null +++ b/drivers/input/input_analog_axis.c @@ -0,0 +1,271 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT analog_axis + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(analog_axis, CONFIG_INPUT_LOG_LEVEL); + +struct analog_axis_channel_config { + struct adc_dt_spec adc; + int16_t out_min; + int16_t out_max; + uint16_t axis; + bool invert; +}; + +struct analog_axis_channel_data { + int last_out; +}; + +struct analog_axis_config { + uint32_t poll_period_ms; + const struct analog_axis_channel_config *channel_cfg; + struct analog_axis_channel_data *channel_data; + struct analog_axis_calibration *calibration; + const uint8_t num_channels; +}; + +struct analog_axis_data { + struct k_mutex cal_lock; + analog_axis_raw_data_t raw_data_cb; + struct k_timer timer; + struct k_thread thread; + + K_KERNEL_STACK_MEMBER(thread_stack, + CONFIG_INPUT_ANALOG_AXIS_THREAD_STACK_SIZE); +}; + +int analog_axis_num_axes(const struct device *dev) +{ + const struct analog_axis_config *cfg = dev->config; + + return cfg->num_channels; +} + +int analog_axis_calibration_get(const struct device *dev, + int channel, + struct analog_axis_calibration *out_cal) +{ + const struct analog_axis_config *cfg = dev->config; + struct analog_axis_data *data = dev->data; + struct analog_axis_calibration *cal = &cfg->calibration[channel]; + + if (channel >= cfg->num_channels) { + return -EINVAL; + } + + k_mutex_lock(&data->cal_lock, K_FOREVER); + memcpy(out_cal, cal, sizeof(struct analog_axis_calibration)); + k_mutex_unlock(&data->cal_lock); + + return 0; +} + +void analog_axis_set_raw_data_cb(const struct device *dev, analog_axis_raw_data_t cb) +{ + struct analog_axis_data *data = dev->data; + + k_mutex_lock(&data->cal_lock, K_FOREVER); + data->raw_data_cb = cb; + k_mutex_unlock(&data->cal_lock); +} + +int analog_axis_calibration_set(const struct device *dev, + int channel, + struct analog_axis_calibration *new_cal) +{ + const struct analog_axis_config *cfg = dev->config; + struct analog_axis_data *data = dev->data; + struct analog_axis_calibration *cal = &cfg->calibration[channel]; + + if (channel >= cfg->num_channels) { + return -EINVAL; + } + + k_mutex_lock(&data->cal_lock, K_FOREVER); + memcpy(cal, new_cal, sizeof(struct analog_axis_calibration)); + k_mutex_unlock(&data->cal_lock); + + return 0; +} + +static void analog_axis_loop(const struct device *dev) +{ + const struct analog_axis_config *cfg = dev->config; + struct analog_axis_data *data = dev->data; + int16_t bufs[cfg->num_channels]; + int32_t out; + struct adc_sequence sequence = { + .buffer = bufs, + .buffer_size = sizeof(bufs), + }; + const struct analog_axis_channel_config *axis_cfg_0 = &cfg->channel_cfg[0]; + int err; + int i; + + adc_sequence_init_dt(&axis_cfg_0->adc, &sequence); + + for (i = 0; i < cfg->num_channels; i++) { + const struct analog_axis_channel_config *axis_cfg = &cfg->channel_cfg[i]; + + sequence.channels |= BIT(axis_cfg->adc.channel_id); + } + + err = adc_read(axis_cfg_0->adc.dev, &sequence); + if (err < 0) { + LOG_ERR("Could not read (%d)", err); + return; + } + + k_mutex_lock(&data->cal_lock, K_FOREVER); + + for (i = 0; i < cfg->num_channels; i++) { + const struct analog_axis_channel_config *axis_cfg = &cfg->channel_cfg[i]; + struct analog_axis_channel_data *axis_data = &cfg->channel_data[i]; + struct analog_axis_calibration *cal = &cfg->calibration[i]; + int16_t in_range = cal->in_max - cal->in_min; + int16_t out_range = axis_cfg->out_max - axis_cfg->out_min; + int32_t raw_val = bufs[i]; + + if (axis_cfg->invert) { + raw_val *= -1; + } + + if (data->raw_data_cb != NULL) { + data->raw_data_cb(dev, i, raw_val); + } + + LOG_DBG("%s: ch %d: raw_val: %d", dev->name, i, raw_val); + + out = CLAMP((raw_val - cal->in_min) * out_range / in_range + axis_cfg->out_min, + axis_cfg->out_min, axis_cfg->out_max); + + if (cal->out_deadzone > 0) { + int16_t center = DIV_ROUND_CLOSEST( + axis_cfg->out_max + axis_cfg->out_min, 2); + if (abs(out - center) < cal->out_deadzone) { + out = center; + } + } + + if (axis_data->last_out != out) { + input_report_abs(dev, axis_cfg->axis, out, true, K_FOREVER); + } + axis_data->last_out = out; + } + + k_mutex_unlock(&data->cal_lock); +} + +static void analog_axis_thread(void *arg1, void *arg2, void *arg3) +{ + const struct device *dev = arg1; + const struct analog_axis_config *cfg = dev->config; + struct analog_axis_data *data = dev->data; + int err; + int i; + + for (i = 0; i < cfg->num_channels; i++) { + const struct analog_axis_channel_config *axis_cfg = &cfg->channel_cfg[i]; + + if (!adc_is_ready_dt(&axis_cfg->adc)) { + LOG_ERR("ADC controller device not ready"); + return; + } + + err = adc_channel_setup_dt(&axis_cfg->adc); + if (err < 0) { + LOG_ERR("Could not setup channel #%d (%d)", i, err); + return; + } + } + + k_timer_init(&data->timer, NULL, NULL); + k_timer_start(&data->timer, + K_MSEC(cfg->poll_period_ms), K_MSEC(cfg->poll_period_ms)); + + while (true) { + analog_axis_loop(dev); + k_timer_status_sync(&data->timer); + } +} + +static int analog_axis_init(const struct device *dev) +{ + struct analog_axis_data *data = dev->data; + k_tid_t tid; + + k_mutex_init(&data->cal_lock); + + tid = k_thread_create(&data->thread, data->thread_stack, + K_KERNEL_STACK_SIZEOF(data->thread_stack), + analog_axis_thread, (void *)dev, NULL, NULL, + CONFIG_INPUT_ANALOG_AXIS_THREAD_PRIORITY, + 0, K_NO_WAIT); + if (!tid) { + LOG_ERR("thread creation failed"); + return -ENODEV; + } + + k_thread_name_set(&data->thread, dev->name); + + return 0; +} + +#define ANALOG_AXIS_CHANNEL_CFG_DEF(node_id) \ + { \ + .adc = ADC_DT_SPEC_GET(node_id), \ + .out_min = (int16_t)DT_PROP(node_id, out_min), \ + .out_max = (int16_t)DT_PROP(node_id, out_max), \ + .axis = DT_PROP(node_id, zephyr_axis), \ + .invert = DT_PROP(node_id, invert), \ + } + +#define ANALOG_AXIS_CHANNEL_CAL_DEF(node_id) \ + { \ + .in_min = (int16_t)DT_PROP(node_id, in_min), \ + .in_max = (int16_t)DT_PROP(node_id, in_max), \ + .out_deadzone = DT_PROP(node_id, out_deadzone), \ + } + +#define ANALOG_AXIS_INIT(inst) \ + static const struct analog_axis_channel_config analog_axis_channel_cfg_##inst[] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(inst, ANALOG_AXIS_CHANNEL_CFG_DEF, (,)) \ + }; \ + \ + static struct analog_axis_channel_data \ + analog_axis_channel_data_##inst[ARRAY_SIZE(analog_axis_channel_cfg_##inst)]; \ + \ + static struct analog_axis_calibration \ + analog_axis_calibration##inst[ARRAY_SIZE(analog_axis_channel_cfg_##inst)] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP( \ + inst, ANALOG_AXIS_CHANNEL_CAL_DEF, (,)) \ + }; \ + \ + static const struct analog_axis_config analog_axis_cfg_##inst = { \ + .poll_period_ms = DT_INST_PROP(inst, poll_period_ms), \ + .channel_cfg = analog_axis_channel_cfg_##inst, \ + .channel_data = analog_axis_channel_data_##inst, \ + .calibration = analog_axis_calibration##inst, \ + .num_channels = ARRAY_SIZE(analog_axis_channel_cfg_##inst), \ + }; \ + \ + static struct analog_axis_data analog_axis_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, analog_axis_init, NULL, \ + &analog_axis_data_##inst, &analog_axis_cfg_##inst, \ + POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(ANALOG_AXIS_INIT) diff --git a/drivers/input/input_analog_axis_settings.c b/drivers/input/input_analog_axis_settings.c new file mode 100644 index 000000000000000..3d29af8b96fec41 --- /dev/null +++ b/drivers/input/input_analog_axis_settings.c @@ -0,0 +1,111 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(analog_axis_settings, CONFIG_INPUT_LOG_LEVEL); + +#define ANALOG_AXIS_SETTINGS_PATH_MAX 32 + +#define MAX_AXES CONFIG_INPUT_ANALOG_AXIS_SETTINGS_MAX_AXES + +static void analog_axis_calibration_log(const struct device *dev) +{ + struct analog_axis_calibration cal; + int i; + + for (i = 0; i < analog_axis_num_axes(dev); i++) { + analog_axis_calibration_get(dev, i, &cal); + + LOG_INF("%s: ch: %d min: %d max: %d deadzone: %d", + dev->name, i, cal.in_min, cal.in_max, cal.out_deadzone); + } +} + +static int analog_axis_calibration_load(const char *key, size_t len_rd, + settings_read_cb read_cb, void *cb_arg) +{ + const struct device *dev; + struct analog_axis_calibration cal[MAX_AXES]; + int axes; + char dev_name[ANALOG_AXIS_SETTINGS_PATH_MAX]; + const char *next; + int nlen; + ssize_t len; + + nlen = settings_name_next(key, &next); + if (nlen + 1 > sizeof(dev_name)) { + LOG_ERR("Setting name too long: %d", nlen); + return -EINVAL; + } + + memcpy(dev_name, key, nlen); + dev_name[nlen] = '\0'; + + dev = device_get_binding(dev_name); + if (dev == NULL) { + LOG_ERR("Cannot restore: device %s not available", dev_name); + return -ENODEV; + } + + len = read_cb(cb_arg, cal, sizeof(cal)); + if (len < 0) { + LOG_ERR("Data restore error: %d", len); + } + + axes = analog_axis_num_axes(dev); + if (len != sizeof(struct analog_axis_calibration) * axes) { + LOG_ERR("Invalid settings data length: %d, expected %d", + len, sizeof(struct analog_axis_calibration) * axes); + return -EIO; + } + + for (int i = 0; i < axes; i++) { + analog_axis_calibration_set(dev, i, &cal[i]); + } + + analog_axis_calibration_log(dev); + + return 0; +} + +SETTINGS_STATIC_HANDLER_DEFINE(analog_axis, "aa-cal", NULL, + analog_axis_calibration_load, NULL, NULL); + +int analog_axis_calibration_save(const struct device *dev) +{ + struct analog_axis_calibration cal[MAX_AXES]; + int axes; + char path[ANALOG_AXIS_SETTINGS_PATH_MAX]; + int ret; + + analog_axis_calibration_log(dev); + + ret = snprintk(path, sizeof(path), "aa-cal/%s", dev->name); + if (ret < 0) { + return -EINVAL; + } + + axes = analog_axis_num_axes(dev); + for (int i = 0; i < axes; i++) { + analog_axis_calibration_get(dev, i, &cal[i]); + } + + ret = settings_save_one(path, &cal[0], + sizeof(struct analog_axis_calibration) * axes); + if (ret < 0) { + LOG_ERR("Settings save errord: %d", ret); + return ret; + } + + return 0; +} diff --git a/drivers/input/input_gpio_keys.c b/drivers/input/input_gpio_keys.c index e9df3cb907d632c..cd277c19fdc9e5d 100644 --- a/drivers/input/input_gpio_keys.c +++ b/drivers/input/input_gpio_keys.c @@ -13,6 +13,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(gpio_keys, CONFIG_INPUT_LOG_LEVEL); @@ -27,35 +28,43 @@ struct gpio_keys_pin_config { /** Zephyr code from devicetree */ uint32_t zephyr_code; }; + +struct gpio_keys_pin_data { + const struct device *dev; + struct gpio_keys_callback cb_data; + struct k_work_delayable work; + int8_t pin_state; +}; + struct gpio_keys_config { /** Debounce interval in milliseconds from devicetree */ uint32_t debounce_interval_ms; const int num_keys; const struct gpio_keys_pin_config *pin_cfg; + struct gpio_keys_pin_data *pin_data; + k_work_handler_t handler; + bool polling_mode; }; -struct gpio_keys_pin_data { - const struct device *dev; - struct gpio_keys_callback cb_data; - struct k_work_delayable work; - int8_t pin_state; +struct gpio_keys_data { +#ifdef CONFIG_PM_DEVICE + atomic_t suspended; +#endif }; /** * Handle debounced gpio pin state. */ -static void gpio_keys_change_deferred(struct k_work *work) +static void gpio_keys_poll_pin(const struct device *dev, int key_index) { - struct k_work_delayable *dwork = k_work_delayable_from_work(work); - struct gpio_keys_pin_data *pin_data = CONTAINER_OF(dwork, struct gpio_keys_pin_data, work); - const struct device *dev = pin_data->dev; - int key_index = pin_data - (struct gpio_keys_pin_data *)dev->data; const struct gpio_keys_config *cfg = dev->config; const struct gpio_keys_pin_config *pin_cfg = &cfg->pin_cfg[key_index]; + struct gpio_keys_pin_data *pin_data = &cfg->pin_data[key_index]; + int new_pressed; - const int new_pressed = gpio_pin_get(pin_cfg->spec.port, pin_cfg->spec.pin); + new_pressed = gpio_pin_get(pin_cfg->spec.port, pin_cfg->spec.pin); - LOG_DBG("gpio_change_deferred %s pin_state=%d, new_pressed=%d, key_index=%d", dev->name, + LOG_DBG("%s: pin_state=%d, new_pressed=%d, key_index=%d", dev->name, pin_data->cb_data.pin_state, new_pressed, key_index); /* If gpio changed, report the event */ @@ -67,6 +76,39 @@ static void gpio_keys_change_deferred(struct k_work *work) } } +static __maybe_unused void gpio_keys_poll_pins(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct gpio_keys_pin_data *pin_data = CONTAINER_OF(dwork, struct gpio_keys_pin_data, work); + const struct device *dev = pin_data->dev; + const struct gpio_keys_config *cfg = dev->config; + +#ifdef CONFIG_PM_DEVICE + struct gpio_keys_data *data = dev->data; + + if (atomic_get(&data->suspended) == 1) { + return; + } +#endif + + for (int i = 0; i < cfg->num_keys; i++) { + gpio_keys_poll_pin(dev, i); + } + + k_work_reschedule(dwork, K_MSEC(cfg->debounce_interval_ms)); +} + +static __maybe_unused void gpio_keys_change_deferred(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct gpio_keys_pin_data *pin_data = CONTAINER_OF(dwork, struct gpio_keys_pin_data, work); + const struct device *dev = pin_data->dev; + const struct gpio_keys_config *cfg = dev->config; + int key_index = pin_data - (struct gpio_keys_pin_data *)cfg->pin_data; + + gpio_keys_poll_pin(dev, key_index); +} + static void gpio_keys_interrupt(const struct device *dev, struct gpio_callback *cbdata, uint32_t pins) { @@ -97,7 +139,7 @@ static int gpio_keys_interrupt_configure(const struct gpio_dt_spec *gpio_spec, cb->pin_state = -1; - LOG_DBG("%s [0x%p, %d]", __func__, gpio_spec->port, gpio_spec->pin); + LOG_DBG("port=%s, pin=%d", gpio_spec->port->name, gpio_spec->pin); ret = gpio_pin_interrupt_configure_dt(gpio_spec, GPIO_INT_EDGE_BOTH); if (ret < 0) { @@ -110,8 +152,8 @@ static int gpio_keys_interrupt_configure(const struct gpio_dt_spec *gpio_spec, static int gpio_keys_init(const struct device *dev) { - struct gpio_keys_pin_data *pin_data = dev->data; const struct gpio_keys_config *cfg = dev->config; + struct gpio_keys_pin_data *pin_data = cfg->pin_data; int ret; for (int i = 0; i < cfg->num_keys; i++) { @@ -129,7 +171,11 @@ static int gpio_keys_init(const struct device *dev) } pin_data[i].dev = dev; - k_work_init_delayable(&pin_data[i].work, gpio_keys_change_deferred); + k_work_init_delayable(&pin_data[i].work, cfg->handler); + + if (cfg->polling_mode) { + continue; + } ret = gpio_keys_interrupt_configure(&cfg->pin_cfg[i].spec, &pin_data[i].cb_data, @@ -140,6 +186,11 @@ static int gpio_keys_init(const struct device *dev) } } + if (cfg->polling_mode) { + /* use pin 0 work to poll all the pins periodically */ + k_work_reschedule(&pin_data[0].work, K_MSEC(cfg->debounce_interval_ms)); + } + ret = pm_device_runtime_enable(dev); if (ret < 0) { LOG_ERR("Failed to enable runtime power management"); @@ -154,6 +205,8 @@ static int gpio_keys_pm_action(const struct device *dev, enum pm_device_action action) { const struct gpio_keys_config *cfg = dev->config; + struct gpio_keys_data *data = dev->data; + struct gpio_keys_pin_data *pin_data = cfg->pin_data; gpio_flags_t gpio_flags; gpio_flags_t int_flags; int ret; @@ -162,10 +215,12 @@ static int gpio_keys_pm_action(const struct device *dev, case PM_DEVICE_ACTION_SUSPEND: gpio_flags = GPIO_DISCONNECTED; int_flags = GPIO_INT_DISABLE; + atomic_set(&data->suspended, 1); break; case PM_DEVICE_ACTION_RESUME: gpio_flags = GPIO_INPUT; int_flags = GPIO_INT_EDGE_BOTH; + atomic_set(&data->suspended, 0); break; default: return -ENOTSUP; @@ -180,6 +235,10 @@ static int gpio_keys_pm_action(const struct device *dev, return ret; } + if (cfg->polling_mode) { + continue; + } + ret = gpio_pin_interrupt_configure_dt(gpio, int_flags); if (ret < 0) { LOG_ERR("interrupt configuration failed: %d", ret); @@ -187,6 +246,11 @@ static int gpio_keys_pm_action(const struct device *dev, } } + if (action == PM_DEVICE_ACTION_RESUME && cfg->polling_mode) { + k_work_reschedule(&pin_data[0].work, + K_MSEC(cfg->debounce_interval_ms)); + } + return 0; } #endif @@ -207,19 +271,25 @@ static int gpio_keys_pm_action(const struct device *dev, static const struct gpio_keys_pin_config gpio_keys_pin_config_##i[] = { \ DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(i, GPIO_KEYS_CFG_DEF, (,))}; \ \ + static struct gpio_keys_pin_data \ + gpio_keys_pin_data_##i[ARRAY_SIZE(gpio_keys_pin_config_##i)]; \ + \ static const struct gpio_keys_config gpio_keys_config_##i = { \ .debounce_interval_ms = DT_INST_PROP(i, debounce_interval_ms), \ .num_keys = ARRAY_SIZE(gpio_keys_pin_config_##i), \ .pin_cfg = gpio_keys_pin_config_##i, \ + .pin_data = gpio_keys_pin_data_##i, \ + .handler = COND_CODE_1(DT_INST_PROP(i, polling_mode), \ + (gpio_keys_poll_pins), (gpio_keys_change_deferred)), \ + .polling_mode = DT_INST_PROP(i, polling_mode), \ }; \ \ - static struct gpio_keys_pin_data \ - gpio_keys_pin_data_##i[ARRAY_SIZE(gpio_keys_pin_config_##i)]; \ + static struct gpio_keys_data gpio_keys_data_##i; \ \ - PM_DEVICE_DT_INST_DEFINE(n, gpio_keys_pm_action); \ + PM_DEVICE_DT_INST_DEFINE(i, gpio_keys_pm_action); \ \ - DEVICE_DT_INST_DEFINE(i, &gpio_keys_init, PM_DEVICE_DT_INST_GET(n), \ - gpio_keys_pin_data_##i, &gpio_keys_config_##i, \ + DEVICE_DT_INST_DEFINE(i, &gpio_keys_init, PM_DEVICE_DT_INST_GET(i), \ + &gpio_keys_data_##i, &gpio_keys_config_##i, \ POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); DT_INST_FOREACH_STATUS_OKAY(GPIO_KEYS_INIT) diff --git a/drivers/input/input_gt911.c b/drivers/input/input_gt911.c index c7f2d5c90b3f4ed..01699c06377128e 100644 --- a/drivers/input/input_gt911.c +++ b/drivers/input/input_gt911.c @@ -17,9 +17,9 @@ LOG_MODULE_REGISTER(gt911, CONFIG_INPUT_LOG_LEVEL); /* GT911 used registers */ -#define DEVICE_ID __bswap_16(0x8140U) -#define REG_STATUS __bswap_16(0x814EU) -#define REG_FIRST_POINT __bswap_16(0x814FU) +#define DEVICE_ID BSWAP_16(0x8140U) +#define REG_STATUS BSWAP_16(0x814EU) +#define REG_FIRST_POINT BSWAP_16(0x814FU) /* REG_TD_STATUS: Touch points. */ #define TOUCH_POINTS_MSK 0x0FU @@ -28,7 +28,7 @@ LOG_MODULE_REGISTER(gt911, CONFIG_INPUT_LOG_LEVEL); #define TOUCH_STATUS_MSK (1 << 7U) /* The GT911's config */ -#define GT911_CONFIG_REG __bswap_16(0x8047U) +#define GT911_CONFIG_REG BSWAP_16(0x8047U) #define REG_CONFIG_VERSION GT911_CONFIG_REG #define REG_CONFIG_SIZE (186U) #define GT911_PRODUCT_ID (0x00313139U) diff --git a/drivers/input/input_kbd_matrix.c b/drivers/input/input_kbd_matrix.c index 2b6c11231e97954..095a9bb0cfd50f2 100644 --- a/drivers/input/input_kbd_matrix.c +++ b/drivers/input/input_kbd_matrix.c @@ -334,6 +334,11 @@ int input_kbd_matrix_actual_key_mask_set(const struct device *dev, return -EINVAL; } + if (cfg->actual_key_mask == NULL) { + LOG_WRN("actual-key-mask not defined for %s", dev->name); + return -EINVAL; + } + WRITE_BIT(cfg->actual_key_mask[col], row, enabled); return 0; diff --git a/drivers/interrupt_controller/intc_plic.c b/drivers/interrupt_controller/intc_plic.c index df50e7b9d3c093f..bdfccced192134e 100644 --- a/drivers/interrupt_controller/intc_plic.c +++ b/drivers/interrupt_controller/intc_plic.c @@ -43,8 +43,8 @@ * However, it is defined and supported by at least the Andes & Telink datasheet, and supported * in Linux's SiFive PLIC driver */ -#define PLIC_TRIG_LEVEL ((uint32_t)~BIT(0)) -#define PLIC_TRIG_EDGE ((uint32_t)BIT(0)) +#define PLIC_TRIG_LEVEL ((uint32_t)0) +#define PLIC_TRIG_EDGE ((uint32_t)1) #define PLIC_DRV_HAS_COMPAT(compat) \ DT_NODE_HAS_COMPAT(DT_COMPAT_GET_ANY_STATUS_OKAY(DT_DRV_COMPAT), compat) @@ -79,7 +79,8 @@ struct plic_config { }; struct plic_stats { - uint16_t *irq_count; + uint16_t *const irq_count; + const int irq_count_len; }; struct plic_data { @@ -227,7 +228,7 @@ static void plic_irq_enable_set_state(uint32_t irq, bool enable) * @brief Enable a riscv PLIC-specific interrupt line * * This routine enables a RISCV PLIC-specific interrupt line. - * riscv_plic_irq_enable is called by SOC_FAMILY_RISCV_PRIVILEGED + * riscv_plic_irq_enable is called by RISCV_PRIVILEGED * arch_irq_enable function to enable external interrupts for * IRQS level == 2, whenever CONFIG_RISCV_HAS_PLIC variable is set. * @@ -242,7 +243,7 @@ void riscv_plic_irq_enable(uint32_t irq) * @brief Disable a riscv PLIC-specific interrupt line * * This routine disables a RISCV PLIC-specific interrupt line. - * riscv_plic_irq_disable is called by SOC_FAMILY_RISCV_PRIVILEGED + * riscv_plic_irq_disable is called by RISCV_PRIVILEGED * arch_irq_disable function to disable external interrupts, for * IRQS level == 2, whenever CONFIG_RISCV_HAS_PLIC variable is set. * @@ -455,7 +456,6 @@ static int cmd_get_stats(const struct shell *sh, size_t argc, char *argv[]) return ret; } - const struct plic_config *config = dev->config; const struct plic_data *data = dev->data; struct plic_stats stat = data->stats; @@ -466,7 +466,7 @@ static int cmd_get_stats(const struct shell *sh, size_t argc, char *argv[]) shell_print(sh, " IRQ\t Hits"); shell_print(sh, "=================="); - for (size_t i = 0; i < MIN(config->num_irqs, CONFIG_MAX_IRQ_PER_AGGREGATOR); i++) { + for (int i = 0; i < stat.irq_count_len; i++) { if (stat.irq_count[i] > min_hit) { shell_print(sh, "%6d\t%10d", i, stat.irq_count[i]); } @@ -485,12 +485,10 @@ static int cmd_clear_stats(const struct shell *sh, size_t argc, char *argv[]) return ret; } - const struct plic_config *config = dev->config; const struct plic_data *data = dev->data; struct plic_stats stat = data->stats; - memset(stat.irq_count, 0, - MIN(config->num_irqs, CONFIG_MAX_IRQ_PER_AGGREGATOR) * sizeof(uint16_t)); + memset(stat.irq_count, 0, stat.irq_count_len * sizeof(uint16_t)); shell_print(sh, "Cleared stats of %s.\n", dev->name); @@ -536,15 +534,16 @@ static int cmd_plic(const struct shell *sh, size_t argc, char **argv) SHELL_CMD_ARG_REGISTER(plic, &plic_cmds, "PLIC shell commands", cmd_plic, 2, 0); +#define PLIC_MIN_IRQ_NUM(n) MIN(DT_INST_PROP(n, riscv_ndev), CONFIG_MAX_IRQ_PER_AGGREGATOR) #define PLIC_INTC_IRQ_COUNT_BUF_DEFINE(n) \ - static uint16_t local_irq_count_##n[MIN(DT_INST_PROP(n, riscv_ndev), \ - CONFIG_MAX_IRQ_PER_AGGREGATOR)]; + static uint16_t local_irq_count_##n[PLIC_MIN_IRQ_NUM(n)]; #define PLIC_INTC_DATA_INIT(n) \ PLIC_INTC_IRQ_COUNT_BUF_DEFINE(n); \ static struct plic_data plic_data_##n = { \ .stats = { \ .irq_count = local_irq_count_##n, \ + .irq_count_len = PLIC_MIN_IRQ_NUM(n), \ }, \ }; diff --git a/drivers/led_strip/CMakeLists.txt b/drivers/led_strip/CMakeLists.txt index 6c950cac5969dff..aa4e95722a7163a 100644 --- a/drivers/led_strip/CMakeLists.txt +++ b/drivers/led_strip/CMakeLists.txt @@ -7,4 +7,5 @@ zephyr_library_sources_ifdef(CONFIG_LPD880X_STRIP lpd880x.c) zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_GPIO ws2812_gpio.c) zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_SPI ws2812_spi.c) zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_I2S ws2812_i2s.c) +zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_RPI_PICO_PIO ws2812_rpi_pico_pio.c) zephyr_library_sources_ifdef(CONFIG_TLC5971_STRIP tlc5971.c) diff --git a/drivers/led_strip/Kconfig.ws2812 b/drivers/led_strip/Kconfig.ws2812 index 7682ba4be87d509..469b6d3f915de64 100644 --- a/drivers/led_strip/Kconfig.ws2812 +++ b/drivers/led_strip/Kconfig.ws2812 @@ -46,4 +46,11 @@ config WS2812_STRIP_GPIO Note that this driver is not compatible with the Everlight B1414 controller. +config WS2812_STRIP_RPI_PICO_PIO + bool "Raspberry Pi Pico PIO" + depends on DT_HAS_WORLDSEMI_WS2812_RPI_PICO_PIO_ENABLED + select PICOSDK_USE_PIO + help + Use the PIO feature available on RaspberryPi Pico devices. + endchoice diff --git a/drivers/led_strip/ws2812_rpi_pico_pio.c b/drivers/led_strip/ws2812_rpi_pico_pio.c new file mode 100644 index 000000000000000..b2bb2654977b36e --- /dev/null +++ b/drivers/led_strip/ws2812_rpi_pico_pio.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2023 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(ws2812_rpi_pico_pio, CONFIG_LED_STRIP_LOG_LEVEL); + +#define DT_DRV_COMPAT worldsemi_ws2812_rpi_pico_pio + +struct ws2812_led_strip_data { + uint32_t sm; +}; + +struct ws2812_led_strip_config { + const struct device *piodev; + uint32_t output_pin; + uint8_t num_colors; + uint32_t frequency; + const uint8_t *const color_mapping; + uint16_t reset_delay; + uint32_t cycles_per_bit; +}; + +struct ws2812_rpi_pico_pio_config { + const struct device *piodev; + const struct pinctrl_dev_config *const pcfg; + struct pio_program program; +}; + +static int ws2812_led_strip_sm_init(const struct device *dev) +{ + const struct ws2812_led_strip_config *config = dev->config; + const float clkdiv = + sys_clock_hw_cycles_per_sec() / (config->cycles_per_bit * config->frequency); + pio_sm_config sm_config = pio_get_default_sm_config(); + PIO pio; + int sm; + + pio = pio_rpi_pico_get_pio(config->piodev); + + sm = pio_claim_unused_sm(pio, false); + if (sm < 0) { + return -EINVAL; + } + + sm_config_set_sideset(&sm_config, 1, false, false); + sm_config_set_sideset_pins(&sm_config, config->output_pin); + sm_config_set_out_shift(&sm_config, false, true, (config->num_colors == 4 ? 32 : 24)); + sm_config_set_fifo_join(&sm_config, PIO_FIFO_JOIN_TX); + sm_config_set_clkdiv(&sm_config, clkdiv); + pio_sm_set_consecutive_pindirs(pio, sm, config->output_pin, 1, true); + pio_sm_init(pio, sm, -1, &sm_config); + pio_sm_set_enabled(pio, sm, true); + + return sm; +} + +/* + * Latch current color values on strip and reset its state machines. + */ +static inline void ws2812_led_strip_reset_delay(uint16_t delay) +{ + k_usleep(delay); +} + +static int ws2812_led_strip_update_rgb(const struct device *dev, struct led_rgb *pixels, + size_t num_pixels) +{ + const struct ws2812_led_strip_config *config = dev->config; + struct ws2812_led_strip_data *data = dev->data; + PIO pio = pio_rpi_pico_get_pio(config->piodev); + + for (size_t i = 0; i < num_pixels; i++) { + uint32_t color = 0; + + for (size_t j = 0; j < config->num_colors; j++) { + switch (config->color_mapping[j]) { + /* White channel is not supported by LED strip API. */ + case LED_COLOR_ID_WHITE: + color |= 0; + break; + case LED_COLOR_ID_RED: + color |= pixels[i].r << (8 * (2 - j)); + break; + case LED_COLOR_ID_GREEN: + color |= pixels[i].g << (8 * (2 - j)); + break; + case LED_COLOR_ID_BLUE: + color |= pixels[i].b << (8 * (2 - j)); + break; + } + } + + pio_sm_put_blocking(pio, data->sm, color << (config->num_colors == 4 ? 0 : 8)); + } + + ws2812_led_strip_reset_delay(config->reset_delay); + + return 0; +} + +static int ws2812_led_strip_update_channels(const struct device *dev, uint8_t *channels, + size_t num_channels) +{ + LOG_DBG("update_channels not implemented"); + return -ENOTSUP; +} + +static const struct led_strip_driver_api ws2812_led_strip_api = { + .update_rgb = ws2812_led_strip_update_rgb, + .update_channels = ws2812_led_strip_update_channels, +}; + +/* + * Retrieve the channel to color mapping (e.g. RGB, BGR, GRB, ...) from the + * "color-mapping" DT property. + */ +static int ws2812_led_strip_init(const struct device *dev) +{ + const struct ws2812_led_strip_config *config = dev->config; + struct ws2812_led_strip_data *data = dev->data; + int sm; + + if (!device_is_ready(config->piodev)) { + LOG_ERR("%s: PIO device not ready", dev->name); + return -ENODEV; + } + + for (uint32_t i = 0; i < config->num_colors; i++) { + switch (config->color_mapping[i]) { + case LED_COLOR_ID_WHITE: + case LED_COLOR_ID_RED: + case LED_COLOR_ID_GREEN: + case LED_COLOR_ID_BLUE: + break; + default: + LOG_ERR("%s: invalid channel to color mapping." + " Check the color-mapping DT property", + dev->name); + return -EINVAL; + } + } + + sm = ws2812_led_strip_sm_init(dev); + if (sm < 0) { + return sm; + } + + data->sm = sm; + + return 0; +} + +static int ws2812_rpi_pico_pio_init(const struct device *dev) +{ + const struct ws2812_rpi_pico_pio_config *config = dev->config; + PIO pio; + + if (!device_is_ready(config->piodev)) { + LOG_ERR("%s: PIO device not ready", dev->name); + return -ENODEV; + } + + pio = pio_rpi_pico_get_pio(config->piodev); + + pio_add_program(pio, &config->program); + + return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); +} + +#define CYCLES_PER_BIT(node) \ + (DT_PROP_BY_IDX(node, bit_waveform, 0) + DT_PROP_BY_IDX(node, bit_waveform, 1) + \ + DT_PROP_BY_IDX(node, bit_waveform, 2)) + +#define WS2812_CHILD_INIT(node) \ + static const uint8_t ws2812_led_strip_##node##_color_mapping[] = \ + DT_PROP(node, color_mapping); \ + struct ws2812_led_strip_data ws2812_led_strip_##node##_data; \ + \ + static const struct ws2812_led_strip_config ws2812_led_strip_##node##_config = { \ + .piodev = DEVICE_DT_GET(DT_PARENT(DT_PARENT(node))), \ + .output_pin = DT_PROP(node, output_pin), \ + .num_colors = DT_PROP_LEN(node, color_mapping), \ + .color_mapping = ws2812_led_strip_##node##_color_mapping, \ + .reset_delay = DT_PROP(node, reset_delay), \ + .frequency = DT_PROP(node, frequency), \ + .cycles_per_bit = CYCLES_PER_BIT(DT_PARENT(node)), \ + }; \ + \ + DEVICE_DT_DEFINE(node, &ws2812_led_strip_init, NULL, &ws2812_led_strip_##node##_data, \ + &ws2812_led_strip_##node##_config, POST_KERNEL, \ + CONFIG_LED_STRIP_INIT_PRIORITY, &ws2812_led_strip_api); + +#define SET_DELAY(op, inst, i) \ + (op | (((DT_INST_PROP_BY_IDX(inst, bit_waveform, i) - 1) & 0xF) << 8)) + +/* + * This pio program runs [T0+T1+T2] cycles per 1 loop. + * The first `out` instruction outputs 0 by [T2] times to the sideset pin. + * These zeros are padding. Here is the start of actual data transmission. + * The second `jmp` instruction output 1 by [T0] times to the sideset pin. + * This `jmp` instruction jumps to line 3 if the value of register x is true. + * Otherwise, jump to line 4. + * The third `jmp` instruction outputs 1 by [T1] times to the sideset pin. + * After output, return to the first line. + * The fourth `jmp` instruction outputs 0 by [T1] times. + * After output, return to the first line and output 0 by [T2] times. + * + * In the case of configuration, T0=3, T1=3, T2 =4, + * the final output is 1110000000 in case register x is false. + * It represents code 0, defined in the datasheet. + * And outputs 1111110000 in case of x is true. It represents code 1. + */ +#define WS2812_RPI_PICO_PIO_INIT(inst) \ + PINCTRL_DT_INST_DEFINE(inst); \ + \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(inst, WS2812_CHILD_INIT); \ + \ + static const uint16_t rpi_pico_pio_ws2812_instructions_##inst[] = { \ + SET_DELAY(0x6021, inst, 2), /* 0: out x, 1 side 0 [T2 - 1] */ \ + SET_DELAY(0x1023, inst, 0), /* 1: jmp !x, 3 side 1 [T0 - 1] */ \ + SET_DELAY(0x1000, inst, 1), /* 2: jmp 0 side 1 [T1 - 1] */ \ + SET_DELAY(0x0000, inst, 1), /* 3: jmp 0 side 0 [T1 - 1] */ \ + }; \ + \ + static const struct ws2812_rpi_pico_pio_config rpi_pico_pio_ws2812_##inst##_config = { \ + .piodev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + .program = \ + { \ + .instructions = rpi_pico_pio_ws2812_instructions_##inst, \ + .length = ARRAY_SIZE(rpi_pico_pio_ws2812_instructions_##inst), \ + .origin = -1, \ + }, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &ws2812_rpi_pico_pio_init, NULL, NULL, \ + &rpi_pico_pio_ws2812_##inst##_config, POST_KERNEL, \ + CONFIG_LED_STRIP_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(WS2812_RPI_PICO_PIO_INIT) diff --git a/drivers/mdio/CMakeLists.txt b/drivers/mdio/CMakeLists.txt index 033917881873705..30c6b9f83062041 100644 --- a/drivers/mdio/CMakeLists.txt +++ b/drivers/mdio/CMakeLists.txt @@ -10,3 +10,4 @@ zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_S32_GMAC mdio_nxp_s32_gmac.c) zephyr_library_sources_ifdef(CONFIG_MDIO_ADIN2111 mdio_adin2111.c) zephyr_library_sources_ifdef(CONFIG_MDIO_GPIO mdio_gpio.c) zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_ENET mdio_nxp_enet.c) +zephyr_library_sources_ifdef(CONFIG_MDIO_INFINEON_XMC4XXX mdio_xmc4xxx.c) diff --git a/drivers/mdio/Kconfig b/drivers/mdio/Kconfig index 7e72b50ceb159df..2ff20df0b24d1e9 100644 --- a/drivers/mdio/Kconfig +++ b/drivers/mdio/Kconfig @@ -31,6 +31,7 @@ source "drivers/mdio/Kconfig.nxp_s32_gmac" source "drivers/mdio/Kconfig.adin2111" source "drivers/mdio/Kconfig.gpio" source "drivers/mdio/Kconfig.nxp_enet" +source "drivers/mdio/Kconfig.xmc4xxx" config MDIO_INIT_PRIORITY int "Init priority" diff --git a/drivers/mdio/Kconfig.xmc4xxx b/drivers/mdio/Kconfig.xmc4xxx new file mode 100644 index 000000000000000..75793fa1508c329 --- /dev/null +++ b/drivers/mdio/Kconfig.xmc4xxx @@ -0,0 +1,9 @@ +# Copyright (c) 2023 SLB +# SPDX-License-Identifier: Apache-2.0 + +config MDIO_INFINEON_XMC4XXX + bool "Infineon XMC4XXX MDIO driver" + default y + depends on DT_HAS_INFINEON_XMC4XXX_MDIO_ENABLED + help + Enable Infineon XMC4XXX MDIO driver. diff --git a/drivers/mdio/mdio_nxp_enet.c b/drivers/mdio/mdio_nxp_enet.c index 1a5c54145b42873..6b5c128e075b77f 100644 --- a/drivers/mdio/mdio_nxp_enet.c +++ b/drivers/mdio/mdio_nxp_enet.c @@ -243,6 +243,7 @@ void nxp_enet_mdio_callback(const struct device *dev, data->interrupt_up = true; break; default: + break; } } diff --git a/drivers/mdio/mdio_shell.c b/drivers/mdio/mdio_shell.c index 4cde88a009ffe43..376e95244faee3c 100644 --- a/drivers/mdio/mdio_shell.c +++ b/drivers/mdio/mdio_shell.c @@ -31,6 +31,8 @@ LOG_MODULE_REGISTER(mdio_shell, CONFIG_LOG_DEFAULT_LEVEL); #define DT_DRV_COMPAT zephyr_mdio_gpio #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_enet_mdio) #define DT_DRV_COMPAT nxp_enet_mdio +#elif DT_HAS_COMPAT_STATUS_OKAY(infineon_xmc4xxx_mdio) +#define DT_DRV_COMPAT infineon_xmc4xxx_mdio #else #error "No known devicetree compatible match for MDIO shell" #endif diff --git a/drivers/mdio/mdio_xmc4xxx.c b/drivers/mdio/mdio_xmc4xxx.c new file mode 100644 index 000000000000000..02ebfc5096d8488 --- /dev/null +++ b/drivers/mdio/mdio_xmc4xxx.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT infineon_xmc4xxx_mdio + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(mdio_xmc4xxx, CONFIG_MDIO_LOG_LEVEL); + +#define MDIO_TRANSFER_TIMEOUT_US 250000 + +#define MAX_MDC_FREQUENCY 2500000u /* 400ns period */ +#define MIN_MDC_FREQUENCY 1000000u /* 1us period */ + +struct mdio_xmc4xxx_clock_divider { + uint8_t divider; + uint8_t reg_val; +}; + +static const struct mdio_xmc4xxx_clock_divider mdio_clock_divider[] = { + {.divider = 8, .reg_val = 2}, {.divider = 13, .reg_val = 3}, + {.divider = 21, .reg_val = 0}, {.divider = 31, .reg_val = 1}, + {.divider = 51, .reg_val = 4}, {.divider = 62, .reg_val = 5}, +}; + +struct mdio_xmc4xxx_dev_data { + struct k_mutex mutex; + uint32_t reg_value_gmii_address; +}; + +struct mdio_xmc4xxx_dev_config { + ETH_GLOBAL_TypeDef *const regs; + const struct pinctrl_dev_config *pcfg; + uint8_t mdi_port_ctrl; +}; + +static int mdio_xmc4xxx_transfer(const struct device *dev, uint8_t phy_addr, uint8_t reg_addr, + uint8_t is_write, uint16_t data_write, uint16_t *data_read) +{ + const struct mdio_xmc4xxx_dev_config *const dev_cfg = dev->config; + ETH_GLOBAL_TypeDef *const regs = dev_cfg->regs; + struct mdio_xmc4xxx_dev_data *const dev_data = dev->data; + uint32_t reg; + int ret = 0; + + k_mutex_lock(&dev_data->mutex, K_FOREVER); + + if ((regs->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0) { + ret = -EBUSY; + goto finish; + } + + reg = dev_data->reg_value_gmii_address; + if (is_write) { + reg |= ETH_GMII_ADDRESS_MW_Msk; + regs->GMII_DATA = data_write; + } + + regs->GMII_ADDRESS = reg | ETH_GMII_ADDRESS_MB_Msk | + FIELD_PREP(ETH_GMII_ADDRESS_PA_Msk, phy_addr) | + FIELD_PREP(ETH_GMII_ADDRESS_MR_Msk, reg_addr); + + if (!WAIT_FOR((regs->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) == 0, + MDIO_TRANSFER_TIMEOUT_US, k_msleep(5))) { + LOG_WRN("mdio transfer timedout"); + ret = -ETIMEDOUT; + goto finish; + } + + if (!is_write && data_read != NULL) { + *data_read = regs->GMII_DATA; + } + +finish: + k_mutex_unlock(&dev_data->mutex); + + return ret; +} + +static int mdio_xmc4xxx_read(const struct device *dev, uint8_t phy_addr, uint8_t reg_addr, + uint16_t *data) +{ + return mdio_xmc4xxx_transfer(dev, phy_addr, reg_addr, 0, 0, data); +} + +static int mdio_xmc4xxx_write(const struct device *dev, uint8_t phy_addr, + uint8_t reg_addr, uint16_t data) +{ + return mdio_xmc4xxx_transfer(dev, phy_addr, reg_addr, 1, data, NULL); +} + +static void mdio_xmc4xxx_bus_enable(const struct device *dev) +{ + ARG_UNUSED(dev); + /* this will enable the clock for ETH, which generates to MDIO clk */ + XMC_ETH_MAC_Enable(NULL); +} + +static void mdio_xmc4xxx_bus_disable(const struct device *dev) +{ + ARG_UNUSED(dev); + XMC_ETH_MAC_Disable(NULL); +} + +static int mdio_xmc4xxx_set_clock_divider(const struct device *dev) +{ + struct mdio_xmc4xxx_dev_data *dev_data = dev->data; + uint32_t eth_mac_clk = XMC_SCU_CLOCK_GetEthernetClockFrequency(); + + for (int i = 0; i < ARRAY_SIZE(mdio_clock_divider); i++) { + uint8_t divider = mdio_clock_divider[i].divider; + uint8_t reg_val = mdio_clock_divider[i].reg_val; + uint32_t mdc_clk = eth_mac_clk / divider; + + if (mdc_clk > MIN_MDC_FREQUENCY && mdc_clk < MAX_MDC_FREQUENCY) { + LOG_DBG("Using MDC clock divider %d", divider); + LOG_DBG("MDC clock %dHz", mdc_clk); + dev_data->reg_value_gmii_address = + FIELD_PREP(ETH_GMII_ADDRESS_CR_Msk, reg_val); + return 0; + } + } + + return -EINVAL; +} + +static int mdio_xmc4xxx_initialize(const struct device *dev) +{ + const struct mdio_xmc4xxx_dev_config *dev_cfg = dev->config; + struct mdio_xmc4xxx_dev_data *dev_data = dev->data; + XMC_ETH_MAC_PORT_CTRL_t port_ctrl = {0}; + int ret; + + k_mutex_init(&dev_data->mutex); + + ret = pinctrl_apply_state(dev_cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret != 0) { + return ret; + } + + ret = mdio_xmc4xxx_set_clock_divider(dev); + if (ret != 0) { + LOG_ERR("Error setting MDIO clock divider"); + return -EINVAL; + } + + port_ctrl.mdio = dev_cfg->mdi_port_ctrl; + ETH0_CON->CON = port_ctrl.raw; + + return ret; +} + +static const struct mdio_driver_api mdio_xmc4xxx_driver_api = { + .read = mdio_xmc4xxx_read, + .write = mdio_xmc4xxx_write, + .bus_enable = mdio_xmc4xxx_bus_enable, + .bus_disable = mdio_xmc4xxx_bus_disable, +}; + +PINCTRL_DT_INST_DEFINE(0); +static const struct mdio_xmc4xxx_dev_config mdio_xmc4xxx_dev_config_0 = { + .regs = (ETH_GLOBAL_TypeDef *)DT_REG_ADDR(DT_INST_PARENT(0)), + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), + .mdi_port_ctrl = DT_INST_ENUM_IDX(0, mdi_port_ctrl), +}; + +static struct mdio_xmc4xxx_dev_data mdio_xmc4xxx_dev_data_0; + +DEVICE_DT_INST_DEFINE(0, &mdio_xmc4xxx_initialize, NULL, &mdio_xmc4xxx_dev_data_0, + &mdio_xmc4xxx_dev_config_0, POST_KERNEL, + CONFIG_MDIO_INIT_PRIORITY, &mdio_xmc4xxx_driver_api); diff --git a/drivers/mfd/mfd_ad5592.c b/drivers/mfd/mfd_ad5592.c index d8f8f60de39a04d..2c320fa549e0ebc 100644 --- a/drivers/mfd/mfd_ad5592.c +++ b/drivers/mfd/mfd_ad5592.c @@ -15,8 +15,9 @@ #define AD5592_GPIO_READBACK_EN BIT(10) #define AD5592_LDAC_READBACK_EN BIT(6) #define AD5592_REG_SOFTWARE_RESET 0x0FU -#define AD5592_SOFTWARE_RESET_MAGIC_VAL 0xDAC -#define AD5592_REV_VAL_MASK 0x3FF +#define AD5592_SOFTWARE_RESET_MAGIC_VAL 0x5AC +#define AD5592_REG_VAL_MASK 0x3FF +#define AD5592_REG_RESET_VAL_MASK 0x7FF #define AD5592_REG_SHIFT_VAL 11 #define AD5592_REG_READBACK_SHIFT_VAL 2 @@ -115,7 +116,19 @@ int mfd_ad5592_read_reg(const struct device *dev, uint8_t reg, uint8_t reg_data, int mfd_ad5592_write_reg(const struct device *dev, uint8_t reg, uint16_t val) { - uint16_t msg = sys_cpu_to_be16((reg << AD5592_REG_SHIFT_VAL) | (val & AD5592_REV_VAL_MASK)); + uint16_t write_mask; + uint16_t msg; + + switch (reg) { + case AD5592_REG_SOFTWARE_RESET: + write_mask = AD5592_REG_RESET_VAL_MASK; + break; + default: + write_mask = AD5592_REG_VAL_MASK; + break; + } + + msg = sys_cpu_to_be16((reg << AD5592_REG_SHIFT_VAL) | (val & write_mask)); return mfd_ad5592_write_raw(dev, msg); } diff --git a/drivers/pwm/pwm_mcux_ftm.c b/drivers/pwm/pwm_mcux_ftm.c index 0f9d7deccf2901f..9f57be2dd711651 100644 --- a/drivers/pwm/pwm_mcux_ftm.c +++ b/drivers/pwm/pwm_mcux_ftm.c @@ -383,11 +383,24 @@ static void mcux_ftm_capture_second_edge(const struct device *dev, uint32_t chan } } -static void mcux_ftm_isr(const struct device *dev) +static bool mcux_ftm_handle_overflow(const struct device *dev) { const struct mcux_ftm_config *config = dev->config; struct mcux_ftm_data *data = dev->data; - bool overflow = false; + + if (FTM_GetStatusFlags(config->base) & kFTM_TimeOverflowFlag) { + data->overflows++; + FTM_ClearStatusFlags(config->base, kFTM_TimeOverflowFlag); + return true; + } + + return false; +} + +static void mcux_ftm_irq_handler(const struct device *dev, uint32_t chan_start, uint32_t chan_end) +{ + const struct mcux_ftm_config *config = dev->config; + bool overflow; uint32_t flags; uint32_t irqs; uint16_t cnt; @@ -397,13 +410,9 @@ static void mcux_ftm_isr(const struct device *dev) irqs = FTM_GetEnabledInterrupts(config->base); cnt = config->base->CNT; - if (flags & kFTM_TimeOverflowFlag) { - data->overflows++; - overflow = true; - FTM_ClearStatusFlags(config->base, kFTM_TimeOverflowFlag); - } + overflow = mcux_ftm_handle_overflow(dev); - for (ch = 0; ch < MAX_CHANNELS; ch++) { + for (ch = chan_start; ch < chan_end; ch++) { if ((flags & BIT(ch)) && (irqs & BIT(ch))) { if (ch & 1) { mcux_ftm_capture_second_edge(dev, ch, cnt, overflow); @@ -496,6 +505,14 @@ static const struct pwm_driver_api mcux_ftm_driver_api = { #define TO_FTM_PRESCALE_DIVIDE(val) _DO_CONCAT(kFTM_Prescale_Divide_, val) #ifdef CONFIG_PWM_CAPTURE +#if IS_EQ(DT_NUM_IRQS(DT_DRV_INST(0)), 1) +static void mcux_ftm_isr(const struct device *dev) +{ + const struct mcux_ftm_config *cfg = dev->config; + + mcux_ftm_irq_handler(dev, 0, cfg->channel_count); +} + #define FTM_CONFIG_FUNC(n) \ static void mcux_ftm_config_func_##n(const struct device *dev) \ { \ @@ -503,6 +520,49 @@ static void mcux_ftm_config_func_##n(const struct device *dev) \ mcux_ftm_isr, DEVICE_DT_INST_GET(n), 0); \ irq_enable(DT_INST_IRQN(n)); \ } +#else /* Multiple interrupts */ +#define FTM_ISR_FUNC_NAME(suffix) _DO_CONCAT(mcux_ftm_isr_, suffix) +#define FTM_ISR_FUNC(chan_start, chan_end) \ +static void mcux_ftm_isr_##chan_start##_##chan_end(const struct device *dev) \ +{ \ + mcux_ftm_irq_handler(dev, chan_start, chan_end + 1); \ +} + +#define FTM_ISR_CONFIG(node_id, prop, idx) \ +do { \ + IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq), \ + DT_IRQ_BY_IDX(node_id, idx, priority), \ + FTM_ISR_FUNC_NAME(DT_STRING_TOKEN_BY_IDX(node_id, prop, idx)), \ + DEVICE_DT_GET(node_id), \ + 0); \ + irq_enable(DT_IRQ_BY_IDX(node_id, idx, irq)); \ +} while (false); + +#define FTM_CONFIG_FUNC(n) \ +static void mcux_ftm_config_func_##n(const struct device *dev) \ +{ \ + DT_INST_FOREACH_PROP_ELEM(n, interrupt_names, FTM_ISR_CONFIG) \ +} + +#if DT_INST_IRQ_HAS_NAME(0, overflow) +static void mcux_ftm_isr_overflow(const struct device *dev) +{ + mcux_ftm_handle_overflow(dev); +} +#endif +#if DT_INST_IRQ_HAS_NAME(0, 0_1) +FTM_ISR_FUNC(0, 1) +#endif +#if DT_INST_IRQ_HAS_NAME(0, 2_3) +FTM_ISR_FUNC(2, 3) +#endif +#if DT_INST_IRQ_HAS_NAME(0, 4_5) +FTM_ISR_FUNC(4, 5) +#endif +#if DT_INST_IRQ_HAS_NAME(0, 6_7) +FTM_ISR_FUNC(6, 7) +#endif +#endif /* IS_EQ(DT_NUM_IRQS(DT_DRV_INST(0)), 1) */ #define FTM_CFG_CAPTURE_INIT(n) \ .irq_config_func = mcux_ftm_config_func_##n #define FTM_INIT_CFG(n) FTM_DECLARE_CFG(n, FTM_CFG_CAPTURE_INIT(n)) diff --git a/drivers/pwm/pwm_nrf_sw.c b/drivers/pwm/pwm_nrf_sw.c index f367bb59899f39a..2b9a22a38f081a0 100644 --- a/drivers/pwm/pwm_nrf_sw.c +++ b/drivers/pwm/pwm_nrf_sw.c @@ -62,6 +62,7 @@ struct pwm_config { NRF_RTC_Type *rtc; NRF_TIMER_Type *timer; }; + nrfx_gpiote_t gpiote[PWM_0_MAP_SIZE]; uint8_t psel_ch[PWM_0_MAP_SIZE]; uint8_t initially_inverted; uint8_t map_size; @@ -123,6 +124,7 @@ static int pwm_nrf_sw_set_cycles(const struct device *dev, uint32_t channel, const struct pwm_config *config = dev->config; NRF_TIMER_Type *timer = pwm_config_timer(config); NRF_RTC_Type *rtc = pwm_config_rtc(config); + NRF_GPIOTE_Type *gpiote; struct pwm_data *data = dev->data; uint32_t ppi_mask; uint8_t active_level; @@ -161,6 +163,7 @@ static int pwm_nrf_sw_set_cycles(const struct device *dev, uint32_t channel, } } + gpiote = config->gpiote[channel].p_reg; psel_ch = config->psel_ch[channel]; gpiote_ch = data->gpiote_ch[channel]; ppi_chs = data->ppi_ch[channel]; @@ -186,7 +189,7 @@ static int pwm_nrf_sw_set_cycles(const struct device *dev, uint32_t channel, : active_level); /* clear GPIOTE config */ - nrf_gpiote_te_default(NRF_GPIOTE, gpiote_ch); + nrf_gpiote_te_default(gpiote, gpiote_ch); /* No PWM generation for this channel. */ data->pulse_cycles[channel] = 0U; @@ -235,7 +238,7 @@ static int pwm_nrf_sw_set_cycles(const struct device *dev, uint32_t channel, } /* Configure GPIOTE - toggle task with proper initial output value. */ - NRF_GPIOTE->CONFIG[gpiote_ch] = + gpiote->CONFIG[gpiote_ch] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | ((uint32_t)psel_ch << 8) | (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) | @@ -256,9 +259,9 @@ static int pwm_nrf_sw_set_cycles(const struct device *dev, uint32_t channel, pulse_end_task = period_end_task = nrf_gpiote_out_task_get(gpiote_ch); #endif uint32_t pulse_end_task_address = - nrf_gpiote_task_address_get(NRF_GPIOTE, pulse_end_task); + nrf_gpiote_task_address_get(gpiote, pulse_end_task); uint32_t period_end_task_address = - nrf_gpiote_task_address_get(NRF_GPIOTE, period_end_task); + nrf_gpiote_task_address_get(gpiote, period_end_task); if (USE_RTC) { uint32_t clear_task_address = @@ -359,7 +362,8 @@ static int pwm_nrf_sw_init(const struct device *dev) } } - err = nrfx_gpiote_channel_alloc(&data->gpiote_ch[i]); + err = nrfx_gpiote_channel_alloc(&config->gpiote[i], + &data->gpiote_ch[i]); if (err != NRFX_SUCCESS) { /* Do not free allocated resource. It is a fatal condition, * system requires reconfiguration. @@ -402,8 +406,14 @@ static int pwm_nrf_sw_init(const struct device *dev) ((DT_GPIO_FLAGS_BY_IDX(_node_id, _prop, _idx) & GPIO_ACTIVE_LOW) \ ? BIT(_idx) : 0) | +#define GPIOTE_AND_COMMA(_node_id, _prop, _idx) \ + NRFX_GPIOTE_INSTANCE(NRF_DT_GPIOTE_INST_BY_IDX(_node_id, _prop, _idx)), + static const struct pwm_config pwm_nrf_sw_0_config = { COND_CODE_1(USE_RTC, (.rtc), (.timer)) = GENERATOR_ADDR, + .gpiote = { + DT_INST_FOREACH_PROP_ELEM(0, channel_gpios, GPIOTE_AND_COMMA) + }, .psel_ch = { DT_INST_FOREACH_PROP_ELEM(0, channel_gpios, PSEL_AND_COMMA) }, diff --git a/drivers/regulator/regulator_common.c b/drivers/regulator/regulator_common.c index 14866a3738f268f..f4f583d6f889971 100644 --- a/drivers/regulator/regulator_common.c +++ b/drivers/regulator/regulator_common.c @@ -49,6 +49,13 @@ int regulator_common_init(const struct device *dev, bool is_enabled) } } + if (config->init_ua > INT32_MIN) { + ret = regulator_set_current_limit(dev, config->init_ua, config->init_ua); + if (ret < 0) { + return ret; + } + } + /* If we have valid range values, we try to match them before enabling */ if ((config->min_uv > INT32_MIN) || (config->max_uv < INT32_MAX)) { diff --git a/drivers/regulator/regulator_max20335.c b/drivers/regulator/regulator_max20335.c index 5395c1de6999604..b94c0e0bb98da6e 100644 --- a/drivers/regulator/regulator_max20335.c +++ b/drivers/regulator/regulator_max20335.c @@ -67,7 +67,7 @@ static const struct linear_range buck12_current_limit_range = static const struct linear_range ldo1_range = LINEAR_RANGE_INIT(800000, 100000U, 0x0U, 0x1CU); static const struct linear_range ldo23_range = LINEAR_RANGE_INIT(900000, 100000U, 0x0U, 0x1FU); -static const struct regulator_max20335_desc buck1_desc = { +static const struct regulator_max20335_desc __maybe_unused buck1_desc = { .vsel_reg = MAX20335_BUCK1_VSET, .enable_mask = MAX20335_BUCK_EN_MASK, .enable_val = MAX20335_BUCK_EN, @@ -76,7 +76,7 @@ static const struct regulator_max20335_desc buck1_desc = { .ua_range = &buck12_current_limit_range, }; -static const struct regulator_max20335_desc buck2_desc = { +static const struct regulator_max20335_desc __maybe_unused buck2_desc = { .vsel_reg = MAX20335_BUCK2_VSET, .enable_mask = MAX20335_BUCK_EN_MASK, .enable_val = MAX20335_BUCK_EN, @@ -85,7 +85,7 @@ static const struct regulator_max20335_desc buck2_desc = { .ua_range = &buck12_current_limit_range, }; -static const struct regulator_max20335_desc ldo1_desc = { +static const struct regulator_max20335_desc __maybe_unused ldo1_desc = { .vsel_reg = MAX20335_LDO1_VSET, .enable_mask = MAX20335_LDO_EN_MASK, .enable_val = MAX20335_LDO_EN, @@ -93,7 +93,7 @@ static const struct regulator_max20335_desc ldo1_desc = { .uv_range = &ldo1_range, }; -static const struct regulator_max20335_desc ldo2_desc = { +static const struct regulator_max20335_desc __maybe_unused ldo2_desc = { .vsel_reg = MAX20335_LDO2_VSET, .enable_mask = MAX20335_LDO_EN_MASK, .enable_val = MAX20335_LDO_EN, @@ -101,7 +101,7 @@ static const struct regulator_max20335_desc ldo2_desc = { .uv_range = &ldo23_range, }; -static const struct regulator_max20335_desc ldo3_desc = { +static const struct regulator_max20335_desc __maybe_unused ldo3_desc = { .vsel_reg = MAX20335_LDO3_VSET, .enable_mask = MAX20335_LDO_EN_MASK, .enable_val = MAX20335_LDO_EN, @@ -224,6 +224,11 @@ static unsigned int regulator_max20335_count_current_limits(const struct device { const struct regulator_max20335_config *config = dev->config; + if (config->source != MAX20335_PMIC_SOURCE_BUCK1 && + config->source != MAX20335_PMIC_SOURCE_BUCK2) { + return -ENOTSUP; + } + return linear_range_values_count(config->desc->ua_range); } @@ -232,6 +237,11 @@ static int regulator_max20335_list_current_limit(const struct device *dev, unsig { const struct regulator_max20335_config *config = dev->config; + if (config->source != MAX20335_PMIC_SOURCE_BUCK1 && + config->source != MAX20335_PMIC_SOURCE_BUCK2) { + return -ENOTSUP; + } + return linear_range_get_value(config->desc->ua_range, idx, current_ua); } @@ -244,6 +254,11 @@ static int regulator_max20335_set_current_limit(const struct device *dev, uint16_t idx; int ret; + if (config->source != MAX20335_PMIC_SOURCE_BUCK1 && + config->source != MAX20335_PMIC_SOURCE_BUCK2) { + return -ENOTSUP; + } + ret = i2c_reg_read_byte_dt(&config->bus, MAX20335_BUCK12_CSET, &val); if (ret < 0) { return ret; diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index 020cd22ae2be603..8e1ee9419b53089 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -77,34 +77,6 @@ struct rtc_stm32_data { struct k_mutex lock; }; -static int rtc_stm32_enter_initialization_mode(bool kernel_available) -{ - if (kernel_available) { - LL_RTC_EnableInitMode(RTC); - bool success = WAIT_FOR(LL_RTC_IsActiveFlag_INIT(RTC), RTC_TIMEOUT, k_msleep(1)); - - if (!success) { - return -EIO; - } - } else { - /* kernel is not available so use the blocking but otherwise equivalent function - * provided by LL - */ - ErrorStatus status = LL_RTC_EnterInitMode(RTC); - - if (status != SUCCESS) { - return -EIO; - } - } - - return 0; -} - -static inline void rtc_stm32_leave_initialization_mode(void) -{ - LL_RTC_DisableInitMode(RTC); -} - static int rtc_stm32_configure(const struct device *dev) { const struct rtc_stm32_config *cfg = dev->config; @@ -123,14 +95,17 @@ static int rtc_stm32_configure(const struct device *dev) if ((hour_format != LL_RTC_HOURFORMAT_24HOUR) || (sync_prescaler != cfg->sync_prescaler) || (async_prescaler != cfg->async_prescaler)) { - err = rtc_stm32_enter_initialization_mode(false); - if (err == 0) { + ErrorStatus status = LL_RTC_EnterInitMode(RTC); + + if (status == SUCCESS) { LL_RTC_SetHourFormat(RTC, LL_RTC_HOURFORMAT_24HOUR); LL_RTC_SetSynchPrescaler(RTC, cfg->sync_prescaler); LL_RTC_SetAsynchPrescaler(RTC, cfg->async_prescaler); + } else { + err = -EIO; } - rtc_stm32_leave_initialization_mode(); + LL_RTC_DisableInitMode(RTC); } #ifdef RTC_CR_BYPSHAD @@ -164,7 +139,6 @@ static int rtc_stm32_init(const struct device *dev) k_mutex_init(&data->lock); /* Enable Backup access */ - z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); #if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) LL_PWR_EnableBkUpAccess(); #endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ @@ -175,12 +149,18 @@ static int rtc_stm32_init(const struct device *dev) return -EIO; } + z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); + LL_RCC_EnableRTC(); z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); err = rtc_stm32_configure(dev); +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) + LL_PWR_DisableBkUpAccess(); +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ + return err; } @@ -208,12 +188,21 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t } LOG_INF("Setting clock"); + +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) + LL_PWR_EnableBkUpAccess(); +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ + LL_RTC_DisableWriteProtection(RTC); - err = rtc_stm32_enter_initialization_mode(true); - if (err) { + ErrorStatus status = LL_RTC_EnterInitMode(RTC); + + if (status != SUCCESS) { +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) + LL_PWR_DisableBkUpAccess(); +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ k_mutex_unlock(&data->lock); - return err; + return -EIO; } LL_RTC_DATE_SetYear(RTC, bin2bcd(real_year - RTC_YEAR_REF)); @@ -233,10 +222,14 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t LL_RTC_TIME_SetMinute(RTC, bin2bcd(timeptr->tm_min)); LL_RTC_TIME_SetSecond(RTC, bin2bcd(timeptr->tm_sec)); - rtc_stm32_leave_initialization_mode(); + LL_RTC_DisableInitMode(RTC); LL_RTC_EnableWriteProtection(RTC); +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) + LL_PWR_DisableBkUpAccess(); +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ + k_mutex_unlock(&data->lock); return err; @@ -359,12 +352,20 @@ static int rtc_stm32_set_calibration(const struct device *dev, int32_t calibrati return -EIO; } +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) + LL_PWR_EnableBkUpAccess(); +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ + LL_RTC_DisableWriteProtection(RTC); MODIFY_REG(RTC->CALR, RTC_CALR_CALP | RTC_CALR_CALM, calp | calm); LL_RTC_EnableWriteProtection(RTC); +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) + LL_PWR_DisableBkUpAccess(); +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ + return 0; } diff --git a/drivers/sensor/icm42688/icm42688_trigger.c b/drivers/sensor/icm42688/icm42688_trigger.c index 32b60f3cd75945d..72ccd7e9059e4c2 100644 --- a/drivers/sensor/icm42688/icm42688_trigger.c +++ b/drivers/sensor/icm42688/icm42688_trigger.c @@ -99,9 +99,7 @@ int icm42688_trigger_set(const struct device *dev, const struct sensor_trigger * data->data_ready_handler = handler; data->data_ready_trigger = trig; - icm42688_lock(dev); - icm42688_spi_read(&cfg->spi, REG_INT_STATUS, &status, 1); - icm42688_unlock(dev); + res = icm42688_spi_read(&cfg->spi, REG_INT_STATUS, &status, 1); break; default: res = -ENOTSUP; diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 3a62057a47abf33..23219f1603675e1 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -1378,8 +1378,9 @@ static void txstopped_isr(const struct device *dev) user_callback(dev, &evt); } -static void uarte_nrfx_isr_async(const struct device *dev) +static void uarte_nrfx_isr_async(const void *arg) { + const struct device *dev = arg; NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = dev->data; @@ -1501,6 +1502,7 @@ static void uarte_nrfx_poll_out(const struct device *dev, unsigned char c) } irq_unlock(key); + Z_SPIN_DELAY(2); } } else { key = wait_tx_ready(dev); @@ -1745,6 +1747,11 @@ static int uarte_instance_init(const struct device *dev, data->dev = dev; +#ifdef CONFIG_ARCH_POSIX + /* For simulation the DT provided peripheral address needs to be corrected */ + ((struct pinctrl_dev_config *)cfg->pcfg)->reg = (uintptr_t)cfg->uarte_regs; +#endif + err = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); if (err < 0) { return err; @@ -1918,6 +1925,7 @@ static int uarte_nrfx_pm_action(const struct device *dev, !nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ERROR)) { /* Busy wait for event to register */ + Z_SPIN_DELAY(2); } nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXTO); @@ -1983,7 +1991,7 @@ static int uarte_nrfx_pm_action(const struct device *dev, }; \ static const struct uarte_nrfx_config uarte_##idx##z_config = { \ .pcfg = PINCTRL_DT_DEV_CONFIG_GET(UARTE(idx)), \ - .uarte_regs = (NRF_UARTE_Type *)DT_REG_ADDR(UARTE(idx)), \ + .uarte_regs = _CONCAT(NRF_UARTE, idx), \ .flags = \ (IS_ENABLED(CONFIG_UART_##idx##_GPIO_MANAGEMENT) ? \ UARTE_CFG_FLAG_GPIO_MGMT : 0) | \ diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index 665b44062accb80..bf07240c0cef522 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -841,7 +841,10 @@ static int uart_ns16550_init(const struct device *dev) data->async.tx_dma_params.dma_cfg.head_block = &data->async.tx_dma_params.active_dma_block; #if defined(CONFIG_UART_NS16550_INTEL_LPSS_DMA) - if (!dev_cfg->io_map) { +#if UART_NS16550_IOPORT_ENABLED + if (!dev_cfg->io_map) +#endif + { uintptr_t base; base = DEVICE_MMIO_GET(dev) + DMA_INTEL_LPSS_OFFSET; diff --git a/drivers/spi/mspi_ambiq.c b/drivers/spi/mspi_ambiq.c index 03ad8b2c0ac7712..0f24fcdfe4f99d9 100644 --- a/drivers/spi/mspi_ambiq.c +++ b/drivers/spi/mspi_ambiq.c @@ -197,7 +197,7 @@ static int mspi_ambiq_release(const struct device *dev, const struct spi_config return 0; } -static struct spi_driver_api mspi_ambiq_driver_api = { +static const struct spi_driver_api mspi_ambiq_driver_api = { .transceive = mspi_ambiq_transceive, .release = mspi_ambiq_release, }; diff --git a/drivers/spi/spi_ambiq.c b/drivers/spi/spi_ambiq.c index 16614798e327015..61d71e3f5671601 100644 --- a/drivers/spi/spi_ambiq.c +++ b/drivers/spi/spi_ambiq.c @@ -219,7 +219,7 @@ static int spi_ambiq_release(const struct device *dev, const struct spi_config * return 0; } -static struct spi_driver_api spi_ambiq_driver_api = { +static const struct spi_driver_api spi_ambiq_driver_api = { .transceive = spi_ambiq_transceive, .release = spi_ambiq_release, }; diff --git a/drivers/spi/spi_andes_atcspi200.c b/drivers/spi/spi_andes_atcspi200.c index 87726fd90caa608..3ae422c767300be 100644 --- a/drivers/spi/spi_andes_atcspi200.c +++ b/drivers/spi/spi_andes_atcspi200.c @@ -283,7 +283,7 @@ int spi_atcspi200_init(const struct device *dev) return 0; } -static struct spi_driver_api spi_atcspi200_api = { +static const struct spi_driver_api spi_atcspi200_api = { .transceive = spi_atcspi200_transceive, #ifdef CONFIG_SPI_ASYNC .transceive_async = spi_atcspi200_transceive_async, diff --git a/drivers/spi/spi_b91.c b/drivers/spi/spi_b91.c index bdc580a521f90b6..ed250eaa62b6810 100644 --- a/drivers/spi/spi_b91.c +++ b/drivers/spi/spi_b91.c @@ -452,7 +452,7 @@ static int spi_b91_release(const struct device *dev, } /* SPI driver APIs structure */ -static struct spi_driver_api spi_b91_api = { +static const struct spi_driver_api spi_b91_api = { .transceive = spi_b91_transceive, .release = spi_b91_release, #ifdef CONFIG_SPI_ASYNC diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index cf6a2973934cbb7..cffd25abd9a0abe 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -247,7 +247,7 @@ int spi_bitbang_release(const struct device *dev, return 0; } -static struct spi_driver_api spi_bitbang_api = { +static const struct spi_driver_api spi_bitbang_api = { .transceive = spi_bitbang_transceive, .release = spi_bitbang_release, #ifdef CONFIG_SPI_ASYNC diff --git a/drivers/spi/spi_emul.c b/drivers/spi/spi_emul.c index 9c8f3a6cd70b5f3..f92d0c951365fe7 100644 --- a/drivers/spi/spi_emul.c +++ b/drivers/spi/spi_emul.c @@ -81,6 +81,18 @@ static int spi_emul_io(const struct device *dev, const struct spi_config *config return api->io(emul->target, config, tx_bufs, rx_bufs); } +/** + * @brief This is a no-op stub of the SPI API's `release` method to protect drivers under test + * from hitting a segmentation fault when using SPI_LOCK_ON plus spi_release() + */ +static int spi_emul_release(const struct device *dev, const struct spi_config *config) +{ + ARG_UNUSED(dev); + ARG_UNUSED(config); + + return 0; +} + /** * Set up a new emulator and add it to the list * @@ -109,8 +121,9 @@ int spi_emul_register(const struct device *dev, struct spi_emul *emul) /* Device instantiation */ -static struct spi_driver_api spi_emul_api = { +static const struct spi_driver_api spi_emul_api = { .transceive = spi_emul_io, + .release = spi_emul_release, }; #define EMUL_LINK_AND_COMMA(node_id) \ diff --git a/drivers/spi/spi_gd32.c b/drivers/spi/spi_gd32.c index 7f9ecaf90fb77aa..c5c37a82f21dc8e 100644 --- a/drivers/spi/spi_gd32.c +++ b/drivers/spi/spi_gd32.c @@ -567,7 +567,7 @@ static int spi_gd32_release(const struct device *dev, return 0; } -static struct spi_driver_api spi_gd32_driver_api = { +static const struct spi_driver_api spi_gd32_driver_api = { .transceive = spi_gd32_transceive, #ifdef CONFIG_SPI_ASYNC .transceive_async = spi_gd32_transceive_async, diff --git a/drivers/spi/spi_gecko.c b/drivers/spi/spi_gecko.c index c223986d8d46094..d07485793b02f48 100644 --- a/drivers/spi/spi_gecko.c +++ b/drivers/spi/spi_gecko.c @@ -357,7 +357,7 @@ static int spi_gecko_release(const struct device *dev, } /* Device Instantiation */ -static struct spi_driver_api spi_gecko_api = { +static const struct spi_driver_api spi_gecko_api = { .transceive = spi_gecko_transceive, #ifdef CONFIG_SPI_ASYNC .transceive_async = spi_gecko_transceive_async, diff --git a/drivers/spi/spi_litespi.c b/drivers/spi/spi_litespi.c index 974f94af5eefb34..dff26a6fc313354 100644 --- a/drivers/spi/spi_litespi.c +++ b/drivers/spi/spi_litespi.c @@ -160,7 +160,7 @@ static int spi_litespi_release(const struct device *dev, } /* Device Instantiation */ -static struct spi_driver_api spi_litespi_api = { +static const struct spi_driver_api spi_litespi_api = { .transceive = spi_litespi_transceive, #ifdef CONFIG_SPI_ASYNC .transceive_async = spi_litespi_transceive_async, diff --git a/drivers/spi/spi_mcux_dspi.c b/drivers/spi/spi_mcux_dspi.c index 63bccd704997854..14d47db4dd983f9 100644 --- a/drivers/spi/spi_mcux_dspi.c +++ b/drivers/spi/spi_mcux_dspi.c @@ -195,11 +195,11 @@ static int spi_mcux_transfer_next_packet(const struct device *dev) status = DSPI_MasterTransferNonBlocking(base, &data->handle, &transfer); if (status != kStatus_Success) { - LOG_ERR("Transfer could not start"); + LOG_ERR("Transfer could not start on %s: %d", dev->name, status); + return status == kDSPI_Busy ? -EBUSY : -EINVAL; } - return status == kStatus_Success ? 0 : - status == kDSPI_Busy ? -EBUSY : -EINVAL; + return 0; } static void spi_mcux_isr(const struct device *dev) diff --git a/drivers/spi/spi_mcux_lpspi.c b/drivers/spi/spi_mcux_lpspi.c index 9bda7a98c9bb286..a1b805d98e0c9ff 100644 --- a/drivers/spi/spi_mcux_lpspi.c +++ b/drivers/spi/spi_mcux_lpspi.c @@ -28,8 +28,13 @@ LOG_MODULE_REGISTER(spi_mcux_lpspi, CONFIG_SPI_LOG_LEVEL); #define CHIP_SELECT_COUNT 4 #define MAX_DATA_WIDTH 4096 +/* Required by DEVICE_MMIO_NAMED_* macros */ +#define DEV_CFG(_dev) \ + ((const struct spi_mcux_config *)(_dev)->config) +#define DEV_DATA(_dev) ((struct spi_mcux_data *)(_dev)->data) + struct spi_mcux_config { - LPSPI_Type *base; + DEVICE_MMIO_NAMED_ROM(reg_base); const struct device *clock_dev; clock_control_subsys_t clock_subsys; void (*irq_config_func)(const struct device *dev); @@ -56,6 +61,7 @@ struct stream { #endif struct spi_mcux_data { + DEVICE_MMIO_NAMED_RAM(reg_base); const struct device *dev; lpspi_master_handle_t handle; struct spi_context ctx; @@ -81,11 +87,11 @@ struct spi_mcux_data { #endif }; -static void spi_mcux_transfer_next_packet(const struct device *dev) +static int spi_mcux_transfer_next_packet(const struct device *dev) { - const struct spi_mcux_config *config = dev->config; + /* const struct spi_mcux_config *config = dev->config; */ struct spi_mcux_data *data = dev->data; - LPSPI_Type *base = config->base; + LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); struct spi_context *ctx = &data->ctx; lpspi_transfer_t transfer; status_t status; @@ -94,11 +100,11 @@ static void spi_mcux_transfer_next_packet(const struct device *dev) /* nothing left to rx or tx, we're done! */ spi_context_cs_control(&data->ctx, false); spi_context_complete(&data->ctx, dev, 0); - return; + return 0; } transfer.configFlags = kLPSPI_MasterPcsContinuous | - (ctx->config->slave << LPSPI_MASTER_PCS_SHIFT); + (ctx->config->slave << LPSPI_MASTER_PCS_SHIFT); if (ctx->tx_len == 0) { /* rx only, nothing to tx */ @@ -144,15 +150,18 @@ static void spi_mcux_transfer_next_packet(const struct device *dev) status = LPSPI_MasterTransferNonBlocking(base, &data->handle, &transfer); if (status != kStatus_Success) { - LOG_ERR("Transfer could not start"); + LOG_ERR("Transfer could not start on %s: %d", dev->name, status); + return status == kStatus_LPSPI_Busy ? -EBUSY : -EINVAL; } + + return 0; } static void spi_mcux_isr(const struct device *dev) { - const struct spi_mcux_config *config = dev->config; + /* const struct spi_mcux_config *config = dev->config; */ struct spi_mcux_data *data = dev->data; - LPSPI_Type *base = config->base; + LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); LPSPI_MasterTransferHandleIRQ(base, &data->handle); } @@ -179,11 +188,11 @@ static void spi_mcux_master_transfer_callback(LPSPI_Type *base, } static int spi_mcux_configure(const struct device *dev, - const struct spi_config *spi_cfg) + const struct spi_config *spi_cfg) { const struct spi_mcux_config *config = dev->config; struct spi_mcux_data *data = dev->data; - LPSPI_Type *base = config->base; + LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); lpspi_master_config_t master_config; uint32_t clock_freq; uint32_t word_size; @@ -202,15 +211,15 @@ static int spi_mcux_configure(const struct device *dev, if (spi_cfg->slave > CHIP_SELECT_COUNT) { LOG_ERR("Slave %d is greater than %d", - spi_cfg->slave, - CHIP_SELECT_COUNT); + spi_cfg->slave, + CHIP_SELECT_COUNT); return -EINVAL; } word_size = SPI_WORD_SIZE_GET(spi_cfg->operation); if (word_size > MAX_DATA_WIDTH) { LOG_ERR("Word size %d is greater than %d", - word_size, MAX_DATA_WIDTH); + word_size, MAX_DATA_WIDTH); return -EINVAL; } @@ -332,10 +341,10 @@ static void spi_mcux_dma_callback(const struct device *dev, void *arg, static int spi_mcux_dma_tx_load(const struct device *dev, const uint8_t *buf, size_t len) { - const struct spi_mcux_config *cfg = dev->config; + /* const struct spi_mcux_config *cfg = dev->config; */ struct spi_mcux_data *data = dev->data; struct dma_block_config *blk_cfg; - LPSPI_Type *base = cfg->base; + LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); /* remember active TX DMA channel (used in callback) */ struct stream *stream = &data->dma_tx; @@ -375,10 +384,10 @@ static int spi_mcux_dma_tx_load(const struct device *dev, const uint8_t *buf, si static int spi_mcux_dma_rx_load(const struct device *dev, uint8_t *buf, size_t len) { - const struct spi_mcux_config *cfg = dev->config; + /*const struct spi_mcux_config *cfg = dev->config; */ struct spi_mcux_data *data = dev->data; struct dma_block_config *blk_cfg; - LPSPI_Type *base = cfg->base; + LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); /* retrieve active RX DMA channel (used in callback) */ struct stream *stream = &data->dma_rx; @@ -477,16 +486,16 @@ static inline int spi_mcux_dma_rxtx_load(const struct device *dev, } static int transceive_dma(const struct device *dev, - const struct spi_config *spi_cfg, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs, - bool asynchronous, - spi_callback_t cb, - void *userdata) + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + bool asynchronous, + spi_callback_t cb, + void *userdata) { - const struct spi_mcux_config *config = dev->config; + /* const struct spi_mcux_config *config = dev->config; */ struct spi_mcux_data *data = dev->data; - LPSPI_Type *base = config->base; + LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); int ret; size_t dma_size; @@ -561,12 +570,12 @@ static int transceive_dma(const struct device *dev, #endif static int transceive(const struct device *dev, - const struct spi_config *spi_cfg, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs, - bool asynchronous, - spi_callback_t cb, - void *userdata) + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + bool asynchronous, + spi_callback_t cb, + void *userdata) { struct spi_mcux_data *data = dev->data; int ret; @@ -582,7 +591,10 @@ static int transceive(const struct device *dev, spi_context_cs_control(&data->ctx, true); - spi_mcux_transfer_next_packet(dev); + ret = spi_mcux_transfer_next_packet(dev); + if (ret) { + goto out; + } ret = spi_context_wait_for_completion(&data->ctx); out: @@ -593,9 +605,9 @@ static int transceive(const struct device *dev, static int spi_mcux_transceive(const struct device *dev, - const struct spi_config *spi_cfg, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs) + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) { #ifdef CONFIG_SPI_MCUX_LPSPI_DMA const struct spi_mcux_data *data = dev->data; @@ -610,11 +622,11 @@ static int spi_mcux_transceive(const struct device *dev, #ifdef CONFIG_SPI_ASYNC static int spi_mcux_transceive_async(const struct device *dev, - const struct spi_config *spi_cfg, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs, - spi_callback_t cb, - void *userdata) + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + spi_callback_t cb, + void *userdata) { #ifdef CONFIG_SPI_MCUX_LPSPI_DMA struct spi_mcux_data *data = dev->data; @@ -631,7 +643,7 @@ static int spi_mcux_transceive_async(const struct device *dev, #endif /* CONFIG_SPI_ASYNC */ static int spi_mcux_release(const struct device *dev, - const struct spi_config *spi_cfg) + const struct spi_config *spi_cfg) { struct spi_mcux_data *data = dev->data; @@ -646,6 +658,8 @@ static int spi_mcux_init(const struct device *dev) const struct spi_mcux_config *config = dev->config; struct spi_mcux_data *data = dev->data; + DEVICE_MMIO_NAMED_MAP(dev, reg_base, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + config->irq_config_func(dev); err = spi_context_cs_configure_all(&data->ctx); @@ -708,19 +722,19 @@ static void spi_mcux_iodev_next(const struct device *dev, bool completion); static void spi_mcux_iodev_start(const struct device *dev) { - const struct spi_mcux_config *config = dev->config; + /* const struct spi_mcux_config *config = dev->config; */ struct spi_mcux_data *data = dev->data; struct rtio_sqe *sqe = &data->txn_curr->sqe; struct spi_dt_spec *spi_dt_spec = sqe->iodev->data; struct spi_config *spi_cfg = &spi_dt_spec->config; struct rtio_iodev_sqe *txn_head = data->txn_head; - LPSPI_Type *base = config->base; + LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); lpspi_transfer_t transfer; status_t status; transfer.configFlags = kLPSPI_MasterPcsContinuous | - (spi_cfg->slave << LPSPI_MASTER_PCS_SHIFT); + (spi_cfg->slave << LPSPI_MASTER_PCS_SHIFT); switch (sqe->op) { case RTIO_OP_RX: @@ -889,7 +903,7 @@ static const struct spi_driver_api spi_mcux_driver_api = { static void spi_mcux_config_func_##n(const struct device *dev); \ \ static const struct spi_mcux_config spi_mcux_config_##n = { \ - .base = (LPSPI_Type *) DT_INST_REG_ADDR(n), \ + DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ .clock_subsys = \ (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name), \ @@ -918,15 +932,15 @@ static const struct spi_driver_api spi_mcux_driver_api = { }; \ \ DEVICE_DT_INST_DEFINE(n, &spi_mcux_init, NULL, \ - &spi_mcux_data_##n, \ - &spi_mcux_config_##n, POST_KERNEL, \ - CONFIG_SPI_INIT_PRIORITY, \ - &spi_mcux_driver_api); \ + &spi_mcux_data_##n, \ + &spi_mcux_config_##n, POST_KERNEL, \ + CONFIG_SPI_INIT_PRIORITY, \ + &spi_mcux_driver_api); \ \ static void spi_mcux_config_func_##n(const struct device *dev) \ { \ IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ - spi_mcux_isr, DEVICE_DT_INST_GET(n), 0); \ + spi_mcux_isr, DEVICE_DT_INST_GET(n), 0); \ \ irq_enable(DT_INST_IRQN(n)); \ } diff --git a/drivers/spi/spi_nrfx_common.c b/drivers/spi/spi_nrfx_common.c index 1ef233cfab3819f..04a11c2367a92f9 100644 --- a/drivers/spi/spi_nrfx_common.c +++ b/drivers/spi/spi_nrfx_common.c @@ -6,40 +6,39 @@ #include "spi_nrfx_common.h" #include -#include -int spi_nrfx_wake_init(uint32_t wake_pin) +int spi_nrfx_wake_init(const nrfx_gpiote_t *gpiote, uint32_t wake_pin) { - nrfx_gpiote_input_config_t input_config = { - .pull = NRF_GPIO_PIN_PULLDOWN, - }; + nrf_gpio_pin_pull_t pull_config = NRF_GPIO_PIN_PULLDOWN; uint8_t ch; nrfx_gpiote_trigger_config_t trigger_config = { .trigger = NRFX_GPIOTE_TRIGGER_HITOLO, .p_in_channel = &ch, }; + nrfx_gpiote_input_pin_config_t input_config = { + .p_pull_config = &pull_config, + .p_trigger_config = &trigger_config, + .p_handler_config = NULL, + }; nrfx_err_t res; - res = nrfx_gpiote_channel_alloc(&ch); + res = nrfx_gpiote_channel_alloc(gpiote, &ch); if (res != NRFX_SUCCESS) { return -ENODEV; } - res = nrfx_gpiote_input_configure(wake_pin, - &input_config, - &trigger_config, - NULL); + res = nrfx_gpiote_input_configure(gpiote, wake_pin, &input_config); if (res != NRFX_SUCCESS) { - nrfx_gpiote_channel_free(ch); + nrfx_gpiote_channel_free(gpiote, ch); return -EIO; } return 0; } -int spi_nrfx_wake_request(uint32_t wake_pin) +int spi_nrfx_wake_request(const nrfx_gpiote_t *gpiote, uint32_t wake_pin) { - nrf_gpiote_event_t trigger_event = nrfx_gpiote_in_event_get(wake_pin); + nrf_gpiote_event_t trigger_event = nrfx_gpiote_in_event_get(gpiote, wake_pin); uint32_t start_cycles; uint32_t max_wait_cycles = DIV_ROUND_UP(CONFIG_SPI_NRFX_WAKE_TIMEOUT_US * @@ -51,7 +50,7 @@ int spi_nrfx_wake_request(uint32_t wake_pin) * The expected time to wait is quite short so it is not worth paying * the overhead of context switching to handle the interrupt. */ - nrfx_gpiote_trigger_enable(wake_pin, false); + nrfx_gpiote_trigger_enable(gpiote, wake_pin, false); /* Enable pull-up on the WAKE line. After the slave device sees the * WAKE line going high, it will force the line to go low. This will * be caught by the enabled trigger and the loop below waits for that. @@ -59,7 +58,7 @@ int spi_nrfx_wake_request(uint32_t wake_pin) nrf_gpio_cfg_input(wake_pin, NRF_GPIO_PIN_PULLUP); start_cycles = k_cycle_get_32(); - while (!nrf_gpiote_event_check(NRF_GPIOTE, trigger_event)) { + while (!nrf_gpiote_event_check(gpiote->p_reg, trigger_event)) { uint32_t elapsed_cycles = k_cycle_get_32() - start_cycles; if (elapsed_cycles >= max_wait_cycles) { @@ -68,7 +67,7 @@ int spi_nrfx_wake_request(uint32_t wake_pin) } } - nrfx_gpiote_trigger_disable(wake_pin); + nrfx_gpiote_trigger_disable(gpiote, wake_pin); nrf_gpio_cfg_input(wake_pin, NRF_GPIO_PIN_PULLDOWN); return err; diff --git a/drivers/spi/spi_nrfx_common.h b/drivers/spi/spi_nrfx_common.h index 515ed5c6f1f2758..0cf17e2a0356de3 100644 --- a/drivers/spi/spi_nrfx_common.h +++ b/drivers/spi/spi_nrfx_common.h @@ -8,10 +8,17 @@ #define ZEPHYR_DRIVERS_SPI_NRFX_COMMON_H_ #include +#include #define WAKE_PIN_NOT_USED UINT32_MAX -int spi_nrfx_wake_init(uint32_t wake_pin); -int spi_nrfx_wake_request(uint32_t wake_pin); +#define WAKE_GPIOTE_INSTANCE(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, wake_gpios), \ + (NRFX_GPIOTE_INSTANCE( \ + NRF_DT_GPIOTE_INST(node_id, wake_gpios))), \ + ({0})) + +int spi_nrfx_wake_init(const nrfx_gpiote_t *gpiote, uint32_t wake_pin); +int spi_nrfx_wake_request(const nrfx_gpiote_t *gpiote, uint32_t wake_pin); #endif /* ZEPHYR_DRIVERS_SPI_NRFX_COMMON_H_ */ diff --git a/drivers/spi/spi_nrfx_spi.c b/drivers/spi/spi_nrfx_spi.c index fd1dc5d933c49a6..752132fb2482340 100644 --- a/drivers/spi/spi_nrfx_spi.c +++ b/drivers/spi/spi_nrfx_spi.c @@ -31,6 +31,7 @@ struct spi_nrfx_config { void (*irq_connect)(void); const struct pinctrl_dev_config *pcfg; uint32_t wake_pin; + nrfx_gpiote_t wake_gpiote; }; static void event_handler(const nrfx_spi_evt_t *p_event, void *p_context); @@ -160,8 +161,6 @@ static void finish_transaction(const struct device *dev, int error) struct spi_nrfx_data *dev_data = dev->data; struct spi_context *ctx = &dev_data->ctx; - spi_context_cs_control(ctx, false); - LOG_DBG("Transaction finished with status %d", error); spi_context_complete(ctx, dev, error); @@ -237,7 +236,8 @@ static int transceive(const struct device *dev, dev_data->busy = true; if (dev_config->wake_pin != WAKE_PIN_NOT_USED) { - error = spi_nrfx_wake_request(dev_config->wake_pin); + error = spi_nrfx_wake_request(&dev_config->wake_gpiote, + dev_config->wake_pin); if (error == -ETIMEDOUT) { LOG_WRN("Waiting for WAKE acknowledgment timed out"); /* If timeout occurs, try to perform the transfer @@ -275,6 +275,8 @@ static int transceive(const struct device *dev, /* Clean up the driver state. */ k_sem_reset(&dev_data->ctx.sync); } + + spi_context_cs_control(&dev_data->ctx, false); } spi_context_release(&dev_data->ctx, error); @@ -381,7 +383,7 @@ static int spi_nrfx_init(const struct device *dev) } if (dev_config->wake_pin != WAKE_PIN_NOT_USED) { - err = spi_nrfx_wake_init(dev_config->wake_pin); + err = spi_nrfx_wake_init(&dev_config->wake_gpiote, dev_config->wake_pin); if (err == -ENODEV) { LOG_ERR("Failed to allocate GPIOTE channel for WAKE"); return err; @@ -444,6 +446,7 @@ static int spi_nrfx_init(const struct device *dev) .pcfg = PINCTRL_DT_DEV_CONFIG_GET(SPI(idx)), \ .wake_pin = NRF_DT_GPIOS_TO_PSEL_OR(SPI(idx), wake_gpios, \ WAKE_PIN_NOT_USED), \ + .wake_gpiote = WAKE_GPIOTE_INSTANCE(SPI(idx)), \ }; \ BUILD_ASSERT(!DT_NODE_HAS_PROP(SPI(idx), wake_gpios) || \ !(DT_GPIO_FLAGS(SPI(idx), wake_gpios) & GPIO_ACTIVE_LOW), \ diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index 1338bd0a4dc6fec..08012b389c55bcd 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -9,7 +9,6 @@ #include #include #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 -#include #include #endif #ifdef CONFIG_SOC_NRF5340_CPUAPP @@ -64,6 +63,7 @@ struct spi_nrfx_config { bool anomaly_58_workaround; #endif uint32_t wake_pin; + nrfx_gpiote_t wake_gpiote; }; static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context); @@ -207,6 +207,8 @@ static int configure(const struct device *dev, } #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 +static const nrfx_gpiote_t gpiote = NRFX_GPIOTE_INSTANCE(0); + /* * Brief Workaround for transmitting 1 byte with SPIM. * @@ -226,15 +228,15 @@ static void anomaly_58_workaround_setup(const struct device *dev) NRF_SPIM_Type *spim = dev_config->spim.p_reg; uint32_t ppi_ch = dev_data->ppi_ch; uint32_t gpiote_ch = dev_data->gpiote_ch; - uint32_t eep = (uint32_t)&NRF_GPIOTE->EVENTS_IN[gpiote_ch]; + uint32_t eep = (uint32_t)&gpiote.p_reg->EVENTS_IN[gpiote_ch]; uint32_t tep = (uint32_t)&spim->TASKS_STOP; dev_data->anomaly_58_workaround_active = true; /* Create an event when SCK toggles */ - nrf_gpiote_event_configure(NRF_GPIOTE, gpiote_ch, spim->PSEL.SCK, + nrf_gpiote_event_configure(gpiote.p_reg, gpiote_ch, spim->PSEL.SCK, GPIOTE_CONFIG_POLARITY_Toggle); - nrf_gpiote_event_enable(NRF_GPIOTE, gpiote_ch); + nrf_gpiote_event_enable(gpiote.p_reg, gpiote_ch); /* Stop the spim instance when SCK toggles */ nrf_ppi_channel_endpoint_setup(NRF_PPI, ppi_ch, eep, tep); @@ -253,7 +255,7 @@ static void anomaly_58_workaround_clear(struct spi_nrfx_data *dev_data) if (dev_data->anomaly_58_workaround_active) { nrf_ppi_channel_disable(NRF_PPI, ppi_ch); - nrf_gpiote_task_disable(NRF_GPIOTE, gpiote_ch); + nrf_gpiote_task_disable(gpiote.p_reg, gpiote_ch); dev_data->anomaly_58_workaround_active = false; } @@ -274,7 +276,7 @@ static int anomaly_58_workaround_init(const struct device *dev) return -ENODEV; } - err_code = nrfx_gpiote_channel_alloc(&dev_data->gpiote_ch); + err_code = nrfx_gpiote_channel_alloc(&gpiote, &dev_data->gpiote_ch); if (err_code != NRFX_SUCCESS) { LOG_ERR("Failed to allocate GPIOTE channel"); return -ENODEV; @@ -292,8 +294,6 @@ static void finish_transaction(const struct device *dev, int error) struct spi_nrfx_data *dev_data = dev->data; struct spi_context *ctx = &dev_data->ctx; - spi_context_cs_control(ctx, false); - LOG_DBG("Transaction finished with status %d", error); spi_context_complete(ctx, dev, error); @@ -426,7 +426,8 @@ static int transceive(const struct device *dev, dev_data->busy = true; if (dev_config->wake_pin != WAKE_PIN_NOT_USED) { - error = spi_nrfx_wake_request(dev_config->wake_pin); + error = spi_nrfx_wake_request(&dev_config->wake_gpiote, + dev_config->wake_pin); if (error == -ETIMEDOUT) { LOG_WRN("Waiting for WAKE acknowledgment timed out"); /* If timeout occurs, try to perform the transfer @@ -467,6 +468,8 @@ static int transceive(const struct device *dev, anomaly_58_workaround_clear(dev_data); #endif } + + spi_context_cs_control(&dev_data->ctx, false); } spi_context_release(&dev_data->ctx, error); @@ -574,7 +577,7 @@ static int spi_nrfx_init(const struct device *dev) } if (dev_config->wake_pin != WAKE_PIN_NOT_USED) { - err = spi_nrfx_wake_init(dev_config->wake_pin); + err = spi_nrfx_wake_init(&dev_config->wake_gpiote, dev_config->wake_pin); if (err == -ENODEV) { LOG_ERR("Failed to allocate GPIOTE channel for WAKE"); return err; @@ -665,6 +668,7 @@ static int spi_nrfx_init(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)), \ }; \ BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \ !(DT_GPIO_FLAGS(SPIM(idx), wake_gpios) & GPIO_ACTIVE_LOW),\ diff --git a/drivers/spi/spi_numaker.c b/drivers/spi/spi_numaker.c index 372f96271ad56c5..eda34014ebb5073 100644 --- a/drivers/spi/spi_numaker.c +++ b/drivers/spi/spi_numaker.c @@ -270,8 +270,10 @@ static int spi_numaker_release(const struct device *dev, const struct spi_config return 0; } -static struct spi_driver_api spi_numaker_driver_api = {.transceive = spi_numaker_transceive, - .release = spi_numaker_release}; +static const struct spi_driver_api spi_numaker_driver_api = { + .transceive = spi_numaker_transceive, + .release = spi_numaker_release +}; static int spi_numaker_init(const struct device *dev) { diff --git a/drivers/spi/spi_oc_simple.c b/drivers/spi/spi_oc_simple.c index 3b8f9c126cfdc72..a0f7296b2a996cc 100644 --- a/drivers/spi/spi_oc_simple.c +++ b/drivers/spi/spi_oc_simple.c @@ -179,7 +179,7 @@ int spi_oc_simple_release(const struct device *dev, return 0; } -static struct spi_driver_api spi_oc_simple_api = { +static const struct spi_driver_api spi_oc_simple_api = { .transceive = spi_oc_simple_transceive, .release = spi_oc_simple_release, #ifdef CONFIG_SPI_ASYNC diff --git a/drivers/spi/spi_opentitan.c b/drivers/spi/spi_opentitan.c index 3116315d9290d00..e8d7b8dc926756d 100644 --- a/drivers/spi/spi_opentitan.c +++ b/drivers/spi/spi_opentitan.c @@ -301,7 +301,7 @@ static int spi_opentitan_release(const struct device *dev, /* Device Instantiation */ -static struct spi_driver_api spi_opentitan_api = { +static const struct spi_driver_api spi_opentitan_api = { .transceive = spi_opentitan_transceive, #ifdef CONFIG_SPI_ASYNC .transceive_async = spi_opentitan_transceive_async, diff --git a/drivers/spi/spi_pl022.c b/drivers/spi/spi_pl022.c index 2565ce669572d62..ed30dddf1e1efb5 100644 --- a/drivers/spi/spi_pl022.c +++ b/drivers/spi/spi_pl022.c @@ -886,7 +886,7 @@ static int spi_pl022_release(const struct device *dev, return 0; } -static struct spi_driver_api spi_pl022_api = { +static const struct spi_driver_api spi_pl022_api = { .transceive = spi_pl022_transceive, #if defined(CONFIG_SPI_ASYNC) .transceive_async = spi_pl022_transceive_async, diff --git a/drivers/spi/spi_rpi_pico_pio.c b/drivers/spi/spi_rpi_pico_pio.c index db348f2d5aa4b0f..ed5179e346683f9 100644 --- a/drivers/spi/spi_rpi_pico_pio.c +++ b/drivers/spi/spi_rpi_pico_pio.c @@ -330,7 +330,7 @@ int spi_pico_pio_release(const struct device *dev, const struct spi_config *spi_ return 0; } -static struct spi_driver_api spi_pico_pio_api = { +static const struct spi_driver_api spi_pico_pio_api = { .transceive = spi_pico_pio_transceive, .release = spi_pico_pio_release, }; diff --git a/drivers/spi/spi_sifive.c b/drivers/spi/spi_sifive.c index c302e67ba80c576..1b5f178c2a602d7 100644 --- a/drivers/spi/spi_sifive.c +++ b/drivers/spi/spi_sifive.c @@ -272,7 +272,7 @@ static int spi_sifive_release(const struct device *dev, /* Device Instantiation */ -static struct spi_driver_api spi_sifive_api = { +static const struct spi_driver_api spi_sifive_api = { .transceive = spi_sifive_transceive, .release = spi_sifive_release, }; diff --git a/drivers/timer/ambiq_stimer.c b/drivers/timer/ambiq_stimer.c index bcef78dd1ac5b9a..8a469f35907bff9 100644 --- a/drivers/timer/ambiq_stimer.c +++ b/drivers/timer/ambiq_stimer.c @@ -80,23 +80,15 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) return; } - k_spinlock_key_t key = k_spin_lock(&g_lock); - - uint64_t now = am_hal_stimer_counter_get(); - uint32_t adj, cyc = ticks * CYC_PER_TICK; - - /* Round up to next tick boundary. */ - adj = (uint32_t)(now - g_last_count) + (CYC_PER_TICK - 1); - if (cyc <= MAX_CYCLES - adj) { - cyc += adj; - } else { - cyc = MAX_CYCLES; + if (ticks == K_TICKS_FOREVER) { + return; } - cyc = (cyc / CYC_PER_TICK) * CYC_PER_TICK; - if ((int32_t)(cyc + g_last_count - now) < MIN_DELAY) { - cyc += CYC_PER_TICK; - } + ticks = MIN(MAX_TICKS, ticks); + /* If tick is 0, set delta cyc to MIN_DELAY to trigger tick isr asap */ + uint32_t cyc = MAX(ticks * CYC_PER_TICK, MIN_DELAY); + + k_spinlock_key_t key = k_spin_lock(&g_lock); am_hal_stimer_compare_delta_set(0, cyc); diff --git a/drivers/usb/device/usb_dc_mcux.c b/drivers/usb/device/usb_dc_mcux.c index 0667486b62806aa..dc0868ffd5da480 100644 --- a/drivers/usb/device/usb_dc_mcux.c +++ b/drivers/usb/device/usb_dc_mcux.c @@ -910,6 +910,9 @@ static void usb_mcux_thread_main(void *arg1, void *arg2, void *arg3) case kUSB_DeviceNotifyResume: dev_state.status_cb(USB_DC_RESUME, NULL); break; + case kUSB_DeviceNotifySOF: + dev_state.status_cb(USB_DC_SOF, NULL); + break; default: ep_abs_idx = EP_ABS_IDX(msg.code); diff --git a/drivers/usb/device/usb_dc_native_posix.c b/drivers/usb/device/usb_dc_native_posix.c index 70410db24403183..c74dad9b35debc2 100644 --- a/drivers/usb/device/usb_dc_native_posix.c +++ b/drivers/usb/device/usb_dc_native_posix.c @@ -605,14 +605,8 @@ int handle_usb_data(struct usbip_header *hdr) LOG_HEXDUMP_DBG(ep_ctrl->buf, ep_ctrl->buf_len, ">"); - /* - * Call the callback only if data in usb_dc_ep_write() - * is actually written to the intermediate buffer and sent. - */ - if (ep_ctrl->buf_len != 0) { - ep_ctrl->cb(ep, USB_DC_EP_DATA_IN); - usbip_ctrl.in_ep_ctrl[ep_idx].buf_len = 0; - } + ep_ctrl->cb(ep, USB_DC_EP_DATA_IN); + ep_ctrl->buf_len = 0; } return 0; diff --git a/drivers/usb/device/usb_dc_rpi_pico.c b/drivers/usb/device/usb_dc_rpi_pico.c index 38e88afae39283b..bb99fa365b285ea 100644 --- a/drivers/usb/device/usb_dc_rpi_pico.c +++ b/drivers/usb/device/usb_dc_rpi_pico.c @@ -655,9 +655,7 @@ int usb_dc_ep_enable(const uint8_t ep) *ep_state->ep_ctl = val; } - if (USB_EP_DIR_IS_OUT(ep) && ep != USB_CONTROL_EP_OUT && - ep_state->cb != usb_transfer_ep_callback) { - /* Start reading now, except for transfer managed eps */ + if (USB_EP_DIR_IS_OUT(ep) && ep != USB_CONTROL_EP_OUT) { return usb_dc_ep_start_read(ep, DATA_BUFFER_SIZE); } diff --git a/drivers/usb/device/usb_dc_stm32.c b/drivers/usb/device/usb_dc_stm32.c index d1434d3ab4b9626..326c6e284a2d557 100644 --- a/drivers/usb/device/usb_dc_stm32.c +++ b/drivers/usb/device/usb_dc_stm32.c @@ -217,13 +217,14 @@ static int usb_dc_stm32_clock_enable(void) return -ENODEV; } -#ifdef PWR_USBSCR_USB33SV +#if defined(PWR_USBSCR_USB33SV) || defined(PWR_SVMCR_USV) + /* * VDDUSB independent USB supply (PWR clock is on) * with LL_PWR_EnableVDDUSB function (higher case) */ LL_PWR_EnableVDDUSB(); -#endif /* PWR_USBSCR_USB33SV */ +#endif /* PWR_USBSCR_USB33SV or PWR_SVMCR_USV */ if (DT_INST_NUM_CLOCKS(0) > 1) { if (clock_control_configure(clk, (clock_control_subsys_t)&pclken[1], diff --git a/drivers/usb/udc/udc_stm32.c b/drivers/usb/udc/udc_stm32.c index bfa3ee8e0f76c7c..e11228619b8f357 100644 --- a/drivers/usb/udc/udc_stm32.c +++ b/drivers/usb/udc/udc_stm32.c @@ -914,13 +914,13 @@ static int priv_clock_enable(void) return -ENODEV; } -#if defined(PWR_USBSCR_USB33SV) +#if defined(PWR_USBSCR_USB33SV) || defined(PWR_SVMCR_USV) /* * VDDUSB independent USB supply (PWR clock is on) * with LL_PWR_EnableVDDUSB function (higher case) */ LL_PWR_EnableVDDUSB(); -#endif /* PWR_USBSCR_USB33SV */ +#endif /* PWR_USBSCR_USB33SV or PWR_SVMCR_USV */ #if defined(CONFIG_SOC_SERIES_STM32H7X) LL_PWR_EnableUSBVoltageDetector(); diff --git a/drivers/w1/CMakeLists.txt b/drivers/w1/CMakeLists.txt index 57d010f4e4d5d05..58fa21ab84a66ef 100644 --- a/drivers/w1/CMakeLists.txt +++ b/drivers/w1/CMakeLists.txt @@ -14,6 +14,7 @@ zephyr_library_sources_ifdef(CONFIG_W1_DS2484 w1_ds2484.c) zephyr_library_sources_ifdef(CONFIG_W1_DS2485 w1_ds2485.c) zephyr_library_sources_ifdef(CONFIG_W1_DS2477_85_COMMON w1_ds2477_85_common.c) zephyr_library_sources_ifdef(CONFIG_W1_TEST w1_test.c) +zephyr_library_sources_ifdef(CONFIG_W1_ZEPHYR_GPIO w1_zephyr_gpio.c) zephyr_library_sources_ifdef(CONFIG_W1_ZEPHYR_SERIAL w1_zephyr_serial.c) # network functions: diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index a63a57419811e36..d33503c26842cc2 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -44,6 +44,7 @@ rsource "Kconfig.ds2484" rsource "Kconfig.ds2477_85" rsource "Kconfig.ds2485" rsource "Kconfig.test" +rsource "Kconfig.zephyr_gpio" rsource "Kconfig.zephyr_serial" config W1_NET diff --git a/drivers/w1/Kconfig.zephyr_gpio b/drivers/w1/Kconfig.zephyr_gpio new file mode 100644 index 000000000000000..57bccfabd91d61a --- /dev/null +++ b/drivers/w1/Kconfig.zephyr_gpio @@ -0,0 +1,28 @@ +# Configuration options for the Zephyr GPIO 1-Wire Master driver + +# Copyright (c) 2023 Hudson C. Dalpra +# SPDX-License-Identifier: Apache-2.0 + +config W1_ZEPHYR_GPIO + bool "1-wire GPIO" + default y + depends on DT_HAS_ZEPHYR_W1_GPIO_ENABLED + help + This option enables the Zephyr GPIO 1-Wire master driver. + + The bus reset, and bit read and write operations are executed + via byte read and write operations on top of the Zephyr + GPIO driver interface. + +if W1_ZEPHYR_GPIO + +config W1_ZEPHYR_GPIO_TIME_CRITICAL + bool "Force time critical operations" + default y + help + This option forces the 1-Wire GPIO driver to use time critical + operations for bus reset, and bit read and write operations. + Time critical communications operations are not interrupted while + being generated. + +endif # W1_ZEPHYR_GPIO diff --git a/drivers/w1/w1_zephyr_gpio.c b/drivers/w1/w1_zephyr_gpio.c new file mode 100644 index 000000000000000..090df881122b5f4 --- /dev/null +++ b/drivers/w1/w1_zephyr_gpio.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2023 Hudson C. Dalpra + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT zephyr_w1_gpio + +/** + * @brief 1-Wire Bus Master driver using Zephyr GPIO interface. + * + * This file contains the implementation of the 1-Wire Bus Master driver using + * the Zephyr GPIO interface. The driver is based on GPIO bit-banging and + * follows the timing specifications for 1-Wire communication. + * + * The driver supports both standard speed and overdrive speed modes. + * + * This driver is heavily based on the w1_zephyr_serial.c driver and the + * technical documentation from Maxim Integrated. + * + * - w1_zephyr_serial.c: drivers/w1/w1_zephyr_serial.c + * - Maxim Integrated 1-Wire Communication Through Software: + * https://www.analog.com/en/technical-articles/1wire-communication-through-software.html + */ + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(w1_gpio, CONFIG_W1_LOG_LEVEL); + +/* + * The time critical sections are used to ensure that the timing + * between communication operations is correct. + */ +#if defined(CONFIG_W1_ZEPHYR_GPIO_TIME_CRITICAL) +#define W1_GPIO_ENTER_CRITICAL() irq_lock() +#define W1_GPIO_EXIT_CRITICAL(key) irq_unlock(key) +#define W1_GPIO_WAIT_US(us) k_busy_wait(us) +#else +#define W1_GPIO_ENTER_CRITICAL() 0u +#define W1_GPIO_EXIT_CRITICAL(key) (void)key +#define W1_GPIO_WAIT_US(us) k_usleep(us) +#endif + +/* + * Standard timing between communication operations: + */ +#define W1_GPIO_TIMING_STD_A 6u +#define W1_GPIO_TIMING_STD_B 64u +#define W1_GPIO_TIMING_STD_C 60u +#define W1_GPIO_TIMING_STD_D 10u +#define W1_GPIO_TIMING_STD_E 9u +#define W1_GPIO_TIMING_STD_F 55u +#define W1_GPIO_TIMING_STD_G 0u +#define W1_GPIO_TIMING_STD_H 480u +#define W1_GPIO_TIMING_STD_I 70u +#define W1_GPIO_TIMING_STD_J 410u + +/* + * Overdrive timing between communication operations: + * + * Not completely correct since the overdrive communication requires + * delays of 2.5us, 7.5us and 8.5us. + * The delays are approximated by flooring the values. + */ +#define W1_GPIO_TIMING_OD_A 1u +#define W1_GPIO_TIMING_OD_B 7u +#define W1_GPIO_TIMING_OD_C 7u +#define W1_GPIO_TIMING_OD_D 2u +#define W1_GPIO_TIMING_OD_E 1u +#define W1_GPIO_TIMING_OD_F 7u +#define W1_GPIO_TIMING_OD_G 2u +#define W1_GPIO_TIMING_OD_H 70u +#define W1_GPIO_TIMING_OD_I 8u +#define W1_GPIO_TIMING_OD_J 40u + +struct w1_gpio_timing { + uint16_t a; + uint16_t b; + uint16_t c; + uint16_t d; + uint16_t e; + uint16_t f; + uint16_t g; + uint16_t h; + uint16_t i; + uint16_t j; +}; + +struct w1_gpio_config { + /** w1 master config, common to all drivers */ + struct w1_master_config master_config; + /** GPIO device used for 1-Wire communication */ + const struct gpio_dt_spec spec; +}; + +struct w1_gpio_data { + /** w1 master data, common to all drivers */ + struct w1_master_data master_data; + /** timing parameters for 1-Wire communication */ + const struct w1_gpio_timing *timing; + /** overdrive speed mode active */ + bool overdrive_active; +}; + +static const struct w1_gpio_timing std = { + .a = W1_GPIO_TIMING_STD_A, + .b = W1_GPIO_TIMING_STD_B, + .c = W1_GPIO_TIMING_STD_C, + .d = W1_GPIO_TIMING_STD_D, + .e = W1_GPIO_TIMING_STD_E, + .f = W1_GPIO_TIMING_STD_F, + .g = W1_GPIO_TIMING_STD_G, + .h = W1_GPIO_TIMING_STD_H, + .i = W1_GPIO_TIMING_STD_I, + .j = W1_GPIO_TIMING_STD_J, +}; + +static const struct w1_gpio_timing od = { + .a = W1_GPIO_TIMING_OD_A, + .b = W1_GPIO_TIMING_OD_B, + .c = W1_GPIO_TIMING_OD_C, + .d = W1_GPIO_TIMING_OD_D, + .e = W1_GPIO_TIMING_OD_E, + .f = W1_GPIO_TIMING_OD_F, + .g = W1_GPIO_TIMING_OD_G, + .h = W1_GPIO_TIMING_OD_H, + .i = W1_GPIO_TIMING_OD_I, + .j = W1_GPIO_TIMING_OD_J, +}; + +static int w1_gpio_reset_bus(const struct device *dev) +{ + const struct w1_gpio_config *cfg = dev->config; + const struct w1_gpio_data *data = dev->data; + + const struct gpio_dt_spec *spec = &cfg->spec; + const struct w1_gpio_timing *timing = data->timing; + + int ret = 0; + unsigned int key = W1_GPIO_ENTER_CRITICAL(); + + W1_GPIO_WAIT_US(timing->g); + ret = gpio_pin_set_dt(spec, 0); + if (ret < 0) { + goto out; + } + + W1_GPIO_WAIT_US(timing->h); + ret = gpio_pin_set_dt(spec, 1); + if (ret < 0) { + goto out; + } + + W1_GPIO_WAIT_US(timing->i); + ret = gpio_pin_get_dt(spec) ^ 0x01; + if (ret < 0) { + goto out; + } + + W1_GPIO_WAIT_US(timing->j); +out: + W1_GPIO_EXIT_CRITICAL(key); + return ret; +} + +static int w1_gpio_read_bit(const struct device *dev) +{ + const struct w1_gpio_config *cfg = dev->config; + const struct w1_gpio_data *data = dev->data; + + const struct gpio_dt_spec *spec = &cfg->spec; + const struct w1_gpio_timing *timing = data->timing; + + int ret = 0; + unsigned int key = W1_GPIO_ENTER_CRITICAL(); + + ret = gpio_pin_set_dt(spec, 0); + if (ret < 0) { + goto out; + } + + W1_GPIO_WAIT_US(timing->a); + ret = gpio_pin_set_dt(spec, 1); + if (ret < 0) { + goto out; + } + + W1_GPIO_WAIT_US(timing->e); + ret = gpio_pin_get_dt(spec) & 0x01; + if (ret < 0) { + goto out; + } + + W1_GPIO_WAIT_US(timing->f); +out: + W1_GPIO_EXIT_CRITICAL(key); + return ret; +} + +static int w1_gpio_write_bit(const struct device *dev, const bool bit) +{ + const struct w1_gpio_config *cfg = dev->config; + const struct w1_gpio_data *data = dev->data; + + const struct gpio_dt_spec *spec = &cfg->spec; + const struct w1_gpio_timing *timing = data->timing; + + int ret = 0; + unsigned int key = W1_GPIO_ENTER_CRITICAL(); + + ret = gpio_pin_set_dt(spec, 0); + if (ret < 0) { + goto out; + } + + W1_GPIO_WAIT_US(bit ? timing->a : timing->c); + ret = gpio_pin_set_dt(spec, 1); + if (ret < 0) { + goto out; + } + + W1_GPIO_WAIT_US(bit ? timing->b : timing->d); +out: + W1_GPIO_EXIT_CRITICAL(key); + return ret; +} + +static int w1_gpio_read_byte(const struct device *dev) +{ + int ret = 0; + int byte = 0x00; + + for (int i = 0; i < 8; i++) { + ret = w1_gpio_read_bit(dev); + if (ret < 0) { + return ret; + } + + byte >>= 1; + if (ret) { + byte |= 0x80; + } + } + + return byte; +} + +static int w1_gpio_write_byte(const struct device *dev, const uint8_t byte) +{ + int ret = 0; + uint8_t write = byte; + + for (int i = 0; i < 8; i++) { + ret = w1_gpio_write_bit(dev, write & 0x01); + if (ret < 0) { + return ret; + } + write >>= 1; + } + + return ret; +} + +static int w1_gpio_configure(const struct device *dev, enum w1_settings_type type, uint32_t value) +{ + struct w1_gpio_data *data = dev->data; + + switch (type) { + case W1_SETTING_SPEED: + data->overdrive_active = (value != 0); + data->timing = data->overdrive_active ? &od : &std; + return 0; + default: + return -ENOTSUP; + } +} + +static int w1_gpio_init(const struct device *dev) +{ + const struct w1_gpio_config *cfg = dev->config; + const struct gpio_dt_spec *spec = &cfg->spec; + struct w1_gpio_data *data = dev->data; + + if (gpio_is_ready_dt(spec)) { + int ret = gpio_pin_configure_dt(spec, GPIO_OUTPUT_INACTIVE | GPIO_OPEN_DRAIN | + GPIO_PULL_UP); + if (ret < 0) { + LOG_ERR("Failed to configure GPIO port %s pin %d", spec->port->name, + spec->pin); + return ret; + } + } else { + LOG_ERR("GPIO port %s is not ready", spec->port->name); + return -ENODEV; + } + + data->timing = &std; + data->overdrive_active = false; + + LOG_DBG("w1-gpio initialized, with %d slave devices", cfg->master_config.slave_count); + return 0; +} + +static const struct w1_driver_api w1_gpio_driver_api = { + .reset_bus = w1_gpio_reset_bus, + .read_bit = w1_gpio_read_bit, + .write_bit = w1_gpio_write_bit, + .read_byte = w1_gpio_read_byte, + .write_byte = w1_gpio_write_byte, + .configure = w1_gpio_configure, +}; + +#define W1_ZEPHYR_GPIO_INIT(inst) \ + static const struct w1_gpio_config w1_gpio_cfg_##inst = { \ + .master_config.slave_count = W1_INST_SLAVE_COUNT(inst), \ + .spec = GPIO_DT_SPEC_INST_GET(inst, gpios)}; \ + static struct w1_gpio_data w1_gpio_data_##inst = {}; \ + DEVICE_DT_INST_DEFINE(inst, &w1_gpio_init, NULL, &w1_gpio_data_##inst, \ + &w1_gpio_cfg_##inst, POST_KERNEL, CONFIG_W1_INIT_PRIORITY, \ + &w1_gpio_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(W1_ZEPHYR_GPIO_INIT) diff --git a/drivers/watchdog/wdt_nrfx.c b/drivers/watchdog/wdt_nrfx.c index 363a1174e916c43..8967d1e162be561 100644 --- a/drivers/watchdog/wdt_nrfx.c +++ b/drivers/watchdog/wdt_nrfx.c @@ -145,8 +145,12 @@ static const struct wdt_driver_api wdt_nrfx_driver_api = { .feed = wdt_nrf_feed, }; -static void wdt_event_handler(const struct device *dev, uint32_t requests) +static void wdt_event_handler(const struct device *dev, nrf_wdt_event_t event_type, + uint32_t requests, void *p_context) { + (void)event_type; + (void)p_context; + struct wdt_nrfx_data *data = dev->data; while (requests) { @@ -162,9 +166,12 @@ static void wdt_event_handler(const struct device *dev, uint32_t requests) #define WDT(idx) DT_NODELABEL(wdt##idx) #define WDT_NRFX_WDT_DEVICE(idx) \ - static void wdt_##idx##_event_handler(uint32_t requests) \ + static void wdt_##idx##_event_handler(nrf_wdt_event_t event_type, \ + uint32_t requests, \ + void *p_context) \ { \ - wdt_event_handler(DEVICE_DT_GET(WDT(idx)), requests); \ + wdt_event_handler(DEVICE_DT_GET(WDT(idx)), event_type, \ + requests, p_context); \ } \ static int wdt_##idx##_init(const struct device *dev) \ { \ @@ -174,7 +181,8 @@ static void wdt_event_handler(const struct device *dev, uint32_t requests) nrfx_isr, nrfx_wdt_##idx##_irq_handler, 0); \ err_code = nrfx_wdt_init(&config->wdt, \ NULL, \ - wdt_##idx##_event_handler); \ + wdt_##idx##_event_handler, \ + NULL); \ if (err_code != NRFX_SUCCESS) { \ return -EBUSY; \ } \ diff --git a/dts/arm/atmel/samc21.dtsi b/dts/arm/atmel/samc21.dtsi index d3cdfbda77729e5..72b28386a4b4b76 100644 --- a/dts/arm/atmel/samc21.dtsi +++ b/dts/arm/atmel/samc21.dtsi @@ -48,7 +48,7 @@ compatible = "atmel,sam0-can"; reg = <0x42001c00 0x100>; interrupts = <15 0>; - interrupt-names = "LINE_0"; + interrupt-names = "int0"; clocks = <&gclk 26>, <&mclk 0x10 8>; clock-names = "GCLK", "MCLK"; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; @@ -62,7 +62,7 @@ compatible = "atmel,sam0-can"; reg = <0x42002000 0x100>; interrupts = <16 0>; - interrupt-names = "LINE_0"; + interrupt-names = "int0"; clocks = <&gclk 27>, <&mclk 0x10 9>; clock-names = "GCLK", "MCLK"; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; diff --git a/dts/arm/atmel/same5x.dtsi b/dts/arm/atmel/same5x.dtsi index 616b408e8edb0d9..c4b1762e5b3581e 100644 --- a/dts/arm/atmel/same5x.dtsi +++ b/dts/arm/atmel/same5x.dtsi @@ -31,7 +31,7 @@ compatible = "atmel,sam0-can"; reg = <0x42000000 0x400>; interrupts = <78 0>, <78 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&gclk 27>, <&mclk 0x10 17>; clock-names = "GCLK", "MCLK"; bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; @@ -45,7 +45,7 @@ compatible = "atmel,sam0-can"; reg = <0x42000400 0x400>; interrupts = <79 0>, <79 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&gclk 28>, <&mclk 0x10 18>; clock-names = "GCLK", "MCLK"; bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; diff --git a/dts/arm/atmel/same70.dtsi b/dts/arm/atmel/same70.dtsi index d15d6baf83e479b..10f103d1ecd5550 100644 --- a/dts/arm/atmel/same70.dtsi +++ b/dts/arm/atmel/same70.dtsi @@ -422,7 +422,7 @@ compatible = "atmel,sam-can"; reg = <0x40030000 0x100>; interrupts = <35 0>, <36 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 35>; divider = <6>; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; @@ -435,7 +435,7 @@ compatible = "atmel,sam-can"; reg = <0x40034000 0x100>; interrupts = <37 0>, <38 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 37>; divider = <6>; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; diff --git a/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi b/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi index fd05d415d3a765b..f0d7d31f9eb9ac7 100644 --- a/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi +++ b/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi @@ -425,4 +425,152 @@ /omit-if-no-ref/ i2c_scl_dout1_p1_10_u0c0: i2c_scl_dout1_p1_10_u0c0 { pinmux = ; }; + + /omit-if-no-ref/ eth_p0_9_mdo: ebu_p0_9_mdo { + pinmux = ; + hwctrl = "periph1"; + }; + /omit-if-no-ref/ eth_p1_11_mdo: ebu_p1_11_mdo { + pinmux = ; + hwctrl = "periph1"; + }; + /omit-if-no-ref/ eth_p2_0_mdo: ebu_p2_0_mdo { + pinmux = ; + hwctrl = "periph1"; + }; + + /omit-if-no-ref/ eth_p0_9_mdio: eth_p0_9_mdio { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_0_mdio: eth_p2_0_mdio { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_11_mdio: eth_p1_11_mdio { + pinmux = ; + }; + + /omit-if-no-ref/ eth_p0_4_tx_en: eth_p0_4_tx_en { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_5_txd0: eth_p0_5_txd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_6_txd1: eth_p0_6_txd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_10_mdc: eth_p0_10_mdc { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_10_mdc: eth_p1_10_mdc { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_12_tx_en: eth_p1_12_tx_en { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_13_txd0: eth_p1_13_txd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_14_txd1: eth_p1_14_txd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_5_tx_en: eth_p2_5_tx_en { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_7_mdc: eth_p2_7_mdc { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_8_txd0: eth_p2_8_txd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_9_txd1: eth_p2_9_txd1 { + pinmux = ; + }; + + /omit-if-no-ref/ eth_p2_2_rxd0: eth_p2_2_rxd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_2_rxd0: eth_p0_2_rxd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p14_8_rxd0: eth_p14_8_rxd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_0_rxd0: eth_p5_0_rxd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_3_rxd1: eth_p2_3_rxd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_3_rxd1: eth_p0_3_rxd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p14_9_rxd1: eth_p14_9_rxd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_1_rxd1: eth_p5_1_rxd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_8_rxd2: eth_p5_8_rxd2 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_4_rxd2: eth_p6_4_rxd2 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_9_rxd3: eth_p5_9_rxd3 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_3_rxd3: eth_p6_3_rxd3 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_1_clk_rmii: eth_p2_1_clk_rmii { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_0_clk_rmii: eth_p0_0_clk_rmii { + pinmux = ; + }; + /omit-if-no-ref/ eth_p15_8_clk_rmii: eth_p15_8_clk_rmii { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_5_clk_rmii: eth_p6_5_clk_rmii { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_5_crs_dv: eth_p2_5_crs_dv { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_1_crs_dv: eth_p0_1_crs_dv { + pinmux = ; + }; + /omit-if-no-ref/ eth_p15_9_crs_dv: eth_p15_9_crs_dv { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_2_crs_dv: eth_p5_2_crs_dv { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_11_crs: eth_p5_11_crs { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_4_crs: eth_p5_4_crs { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_4_rxer: eth_p2_4_rxer { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_11_rxer: eth_p0_11_rxer { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_3_rxer: eth_p5_3_rxer { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_15_col: eth_p2_15_col { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_5_col: eth_p5_5_col { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_10_clk_tx: eth_p5_10_clk_tx { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_6_clk_tx: eth_p6_6_clk_tx { + pinmux = ; + }; }; diff --git a/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi b/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi index 75988d493e78eea..8962aa2731a4287 100644 --- a/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi +++ b/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi @@ -985,4 +985,179 @@ /omit-if-no-ref/ i2c_scl_dout1_p3_9_u2c0: i2c_scl_dout1_p3_9_u2c0 { pinmux = ; }; + + /omit-if-no-ref/ eth_p0_9_mdo: eth_p0_9_mdo { + pinmux = ; + hwctrl = "periph1"; + }; + /omit-if-no-ref/ eth_p1_11_mdo: eth_p1_11_mdo { + pinmux = ; + hwctrl = "periph1"; + }; + /omit-if-no-ref/ eth_p2_0_mdo: eth_p2_0_mdo { + pinmux = ; + hwctrl = "periph1"; + }; + + /omit-if-no-ref/ eth_p0_9_mdio: eth_p0_9_mdio { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_0_mdio: eth_p2_0_mdio { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_11_mdio: eth_p1_11_mdio { + pinmux = ; + }; + + /omit-if-no-ref/ eth_p0_4_tx_en: eth_p0_4_tx_en { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_5_txd0: eth_p0_5_txd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_6_txd1: eth_p0_6_txd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_10_mdc: eth_p0_10_mdc { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_10_mdc: eth_p1_10_mdc { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_12_tx_en: eth_p1_12_tx_en { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_13_txd0: eth_p1_13_txd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p1_14_txd1: eth_p1_14_txd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_5_tx_en: eth_p2_5_tx_en { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_7_mdc: eth_p2_7_mdc { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_8_txd0: eth_p2_8_txd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_9_txd1: eth_p2_9_txd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_11_txer: eth_p2_11_txer { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_12_txd2: eth_p2_12_txd2 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_12_txd0: eth_p2_12_txd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_13_txd3: eth_p2_13_txd3 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_13_txd1: eth_p2_13_txd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_9_tx_en: eth_p5_9_tx_en { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_0_txd2: eth_p6_0_txd2 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_1_txd3: eth_p6_1_txd3 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_2_txer: eth_p6_2_txer { + pinmux = ; + }; + + /omit-if-no-ref/ eth_p2_2_rxd0: eth_p2_2_rxd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_2_rxd0: eth_p0_2_rxd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p14_8_rxd0: eth_p14_8_rxd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_0_rxd0: eth_p5_0_rxd0 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_3_rxd1: eth_p2_3_rxd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_3_rxd1: eth_p0_3_rxd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p14_9_rxd1: eth_p14_9_rxd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_1_rxd1: eth_p5_1_rxd1 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_8_rxd2: eth_p5_8_rxd2 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_4_rxd2: eth_p6_4_rxd2 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_9_rxd3: eth_p5_9_rxd3 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_3_rxd3: eth_p6_3_rxd3 { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_1_clk_rmii: eth_p2_1_clk_rmii { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_0_clk_rmii: eth_p0_0_clk_rmii { + pinmux = ; + }; + /omit-if-no-ref/ eth_p15_8_clk_rmii: eth_p15_8_clk_rmii { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_5_clk_rmii: eth_p6_5_clk_rmii { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_5_crs_dv: eth_p2_5_crs_dv { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_1_crs_dv: eth_p0_1_crs_dv { + pinmux = ; + }; + /omit-if-no-ref/ eth_p15_9_crs_dv: eth_p15_9_crs_dv { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_2_crs_dv: eth_p5_2_crs_dv { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_11_crs: eth_p5_11_crs { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_4_crs: eth_p5_4_crs { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_4_rxer: eth_p2_4_rxer { + pinmux = ; + }; + /omit-if-no-ref/ eth_p0_11_rxer: eth_p0_11_rxer { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_3_rxer: eth_p5_3_rxer { + pinmux = ; + }; + /omit-if-no-ref/ eth_p2_15_col: eth_p2_15_col { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_5_col: eth_p5_5_col { + pinmux = ; + }; + /omit-if-no-ref/ eth_p5_10_clk_tx: eth_p5_10_clk_tx { + pinmux = ; + }; + /omit-if-no-ref/ eth_p6_6_clk_tx: eth_p6_6_clk_tx { + pinmux = ; + }; }; diff --git a/dts/arm/infineon/xmc4700_F144x2048.dtsi b/dts/arm/infineon/xmc4700_F144x2048.dtsi index bd5250050e97c44..22a9eb30404dbaa 100644 --- a/dts/arm/infineon/xmc4700_F144x2048.dtsi +++ b/dts/arm/infineon/xmc4700_F144x2048.dtsi @@ -13,14 +13,9 @@ reg = <0x1ffe8000 DT_SIZE_K(96)>; }; - dsram1: memory@20000000 { + dsram_joined: memory@20000000 { compatible = "mmio-sram"; - reg = <0x20000000 DT_SIZE_K(128)>; - }; - - dsram2: memory@20020000 { - compatible = "mmio-sram"; - reg = <0x20020000 DT_SIZE_K(128)>; + reg = <0x20000000 DT_SIZE_K(256)>; }; }; diff --git a/dts/arm/infineon/xmc4xxx.dtsi b/dts/arm/infineon/xmc4xxx.dtsi index 82845683fc64225..900493481340450 100644 --- a/dts/arm/infineon/xmc4xxx.dtsi +++ b/dts/arm/infineon/xmc4xxx.dtsi @@ -236,6 +236,23 @@ interrupts = <0 1>; status = "disabled"; }; + + ethernet@5000c000 { + reg = <0x5000C000 0x3FFF>; + + eth: ethernet { + compatible = "infineon,xmc4xxx-ethernet"; + interrupts = <108 1>; + status = "disabled"; + }; + + mdio: mdio { + compatible = "infineon,xmc4xxx-mdio"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + }; }; }; diff --git a/dts/arm/nordic/nrf51822.dtsi b/dts/arm/nordic/nrf51822.dtsi index 222ccd4854c3c05..020711a7e7f7f9f 100644 --- a/dts/arm/nordic/nrf51822.dtsi +++ b/dts/arm/nordic/nrf51822.dtsi @@ -131,11 +131,12 @@ status = "disabled"; }; - gpiote: gpiote@40006000 { + gpiote: gpiote0: gpiote@40006000 { compatible = "nordic,nrf-gpiote"; reg = <0x40006000 0x1000>; interrupts = <6 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; + instance = <0>; }; adc: adc@40007000 { @@ -316,6 +317,7 @@ #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; }; }; diff --git a/dts/arm/nordic/nrf52805.dtsi b/dts/arm/nordic/nrf52805.dtsi index dd7845588e7dfe2..a54e8eca9c68eef 100644 --- a/dts/arm/nordic/nrf52805.dtsi +++ b/dts/arm/nordic/nrf52805.dtsi @@ -132,11 +132,12 @@ status = "disabled"; }; - gpiote: gpiote@40006000 { + gpiote: gpiote0: gpiote@40006000 { compatible = "nordic,nrf-gpiote"; reg = <0x40006000 0x1000>; interrupts = <6 5>; status = "disabled"; + instance = <0>; }; adc: adc@40007000 { @@ -311,6 +312,7 @@ #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; }; }; diff --git a/dts/arm/nordic/nrf52810.dtsi b/dts/arm/nordic/nrf52810.dtsi index 82f5afb99f6d2c7..ce5a2bce77981b5 100644 --- a/dts/arm/nordic/nrf52810.dtsi +++ b/dts/arm/nordic/nrf52810.dtsi @@ -136,11 +136,12 @@ status = "disabled"; }; - gpiote: gpiote@40006000 { + gpiote: gpiote0: gpiote@40006000 { compatible = "nordic,nrf-gpiote"; reg = <0x40006000 0x1000>; interrupts = <6 5>; status = "disabled"; + instance = <0>; }; adc: adc@40007000 { @@ -337,6 +338,7 @@ #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; }; }; diff --git a/dts/arm/nordic/nrf52811.dtsi b/dts/arm/nordic/nrf52811.dtsi index 9e03d5edb320f86..9c9a3fa6b771655 100644 --- a/dts/arm/nordic/nrf52811.dtsi +++ b/dts/arm/nordic/nrf52811.dtsi @@ -167,11 +167,12 @@ status = "disabled"; }; - gpiote: gpiote@40006000 { + gpiote: gpiote0: gpiote@40006000 { compatible = "nordic,nrf-gpiote"; reg = <0x40006000 0x1000>; interrupts = <6 5>; status = "disabled"; + instance = <0>; }; adc: adc@40007000 { @@ -372,6 +373,7 @@ #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; }; }; diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index 71ff85afbeb98ef..c210a7c23aa5500 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -180,11 +180,12 @@ status = "disabled"; }; - gpiote: gpiote@40006000 { + gpiote: gpiote0: gpiote@40006000 { compatible = "nordic,nrf-gpiote"; reg = <0x40006000 0x1000>; interrupts = <6 5>; status = "disabled"; + instance = <0>; }; timer0: timer@40008000 { @@ -389,6 +390,7 @@ #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; }; }; diff --git a/dts/arm/nordic/nrf52832.dtsi b/dts/arm/nordic/nrf52832.dtsi index 69de3aa591ad190..2e1fd68946b4a56 100644 --- a/dts/arm/nordic/nrf52832.dtsi +++ b/dts/arm/nordic/nrf52832.dtsi @@ -179,11 +179,12 @@ status = "okay"; }; - gpiote: gpiote@40006000 { + gpiote: gpiote0: gpiote@40006000 { compatible = "nordic,nrf-gpiote"; reg = <0x40006000 0x1000>; interrupts = <6 5>; status = "disabled"; + instance = <0>; }; adc: adc@40007000 { @@ -465,6 +466,7 @@ #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; }; }; diff --git a/dts/arm/nordic/nrf52833.dtsi b/dts/arm/nordic/nrf52833.dtsi index 8003649385cf334..d55f0f6df9e05d1 100644 --- a/dts/arm/nordic/nrf52833.dtsi +++ b/dts/arm/nordic/nrf52833.dtsi @@ -186,11 +186,12 @@ status = "okay"; }; - gpiote: gpiote@40006000 { + gpiote: gpiote0: gpiote@40006000 { compatible = "nordic,nrf-gpiote"; reg = <0x40006000 0x1000>; interrupts = <6 5>; status = "disabled"; + instance = <0>; }; adc: adc@40007000 { @@ -521,6 +522,7 @@ #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; gpio1: gpio@50000300 { @@ -532,6 +534,7 @@ ngpios = <10>; status = "disabled"; port = <1>; + gpiote-instance = <&gpiote>; }; }; }; diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index 24710e8e0ff2e93..e833835198b8ebf 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -181,11 +181,12 @@ status = "okay"; }; - gpiote: gpiote@40006000 { + gpiote: gpiote0: gpiote@40006000 { compatible = "nordic,nrf-gpiote"; reg = <0x40006000 0x1000>; interrupts = <6 5>; status = "disabled"; + instance = <0>; }; adc: adc@40007000 { @@ -525,6 +526,7 @@ #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; gpio1: gpio@50000300 { @@ -536,6 +538,7 @@ ngpios = <16>; status = "disabled"; port = <1>; + gpiote-instance = <&gpiote>; }; cryptocell: crypto@5002a000 { diff --git a/dts/arm/nordic/nrf5340_cpuapp.dtsi b/dts/arm/nordic/nrf5340_cpuapp.dtsi index 77762990e133886..bc6b5316519d499 100644 --- a/dts/arm/nordic/nrf5340_cpuapp.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp.dtsi @@ -84,6 +84,16 @@ reg = <0x5000d000 0x1000>; interrupts = <13 5>; status = "disabled"; + instance = <0>; + }; + + /* Additional Non-Secure GPIOTE instance */ + gpiote1: gpiote@4002f000 { + compatible = "nordic,nrf-gpiote"; + reg = <0x4002f000 0x1000>; + interrupts = <47 5>; + status = "disabled"; + instance = <1>; }; cryptocell: crypto@50844000 { @@ -104,10 +114,3 @@ &nvic { arm,num-irq-priority-bits = <3>; }; - -/* - * Include the non-secure peripherals file here since - * it expects to be at the root level. This provides - * a node for GPIOTE1. - */ -#include "nrf5340_cpuapp_peripherals_ns.dtsi" diff --git a/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi b/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi index 5e2e91f20b76556..94e764ec52cfaf2 100644 --- a/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi @@ -527,6 +527,7 @@ gpio0: gpio@842500 { #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; gpio1: gpio@842800 { @@ -537,6 +538,7 @@ gpio1: gpio@842800 { ngpios = <16>; status = "disabled"; port = <1>; + gpiote-instance = <&gpiote>; }; ieee802154: ieee802154 { diff --git a/dts/arm/nordic/nrf5340_cpuapp_peripherals_ns.dtsi b/dts/arm/nordic/nrf5340_cpuapp_peripherals_ns.dtsi deleted file mode 100644 index 5cfe561e6139df8..000000000000000 --- a/dts/arm/nordic/nrf5340_cpuapp_peripherals_ns.dtsi +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2019 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * GPIOTE1 is always accessible as a non-secure peripheral. - */ - -/ { - soc { - gpiote1: gpiote@4002f000 { - compatible = "nordic,nrf-gpiote"; - reg = <0x4002f000 0x1000>; - interrupts = <47 5>; - status = "disabled"; - }; - }; -}; diff --git a/dts/arm/nordic/nrf5340_cpuappns.dtsi b/dts/arm/nordic/nrf5340_cpuappns.dtsi index b5278745e5d5fce..aa97c3370678b05 100644 --- a/dts/arm/nordic/nrf5340_cpuappns.dtsi +++ b/dts/arm/nordic/nrf5340_cpuappns.dtsi @@ -48,6 +48,19 @@ */ #include "nrf5340_cpuapp_peripherals.dtsi" }; + + /* + * GPIOTE1 is always accessible as a non-secure peripheral, + * so we give it the 'gpiote' label for use when building + * code for this target. + */ + gpiote: gpiote1: gpiote@4002f000 { + compatible = "nordic,nrf-gpiote"; + reg = <0x4002f000 0x1000>; + interrupts = <47 5>; + status = "disabled"; + instance = <1>; + }; }; /* Default IPC description */ @@ -64,12 +77,3 @@ &nvic { arm,num-irq-priority-bits = <3>; }; - -/* - * Include the non-secure peripherals file here since - * it expects to be at the root level, adding a 'gpiote' label - * for the GPIOTE1 peripheral defined in that file which is - * always accessible as a non-secure peripheral. - */ -#include "nrf5340_cpuapp_peripherals_ns.dtsi" -gpiote: &gpiote1 {}; diff --git a/dts/arm/nordic/nrf5340_cpunet.dtsi b/dts/arm/nordic/nrf5340_cpunet.dtsi index 63c7e920f81806e..6c1e66e73aa65c5 100644 --- a/dts/arm/nordic/nrf5340_cpunet.dtsi +++ b/dts/arm/nordic/nrf5340_cpunet.dtsi @@ -108,11 +108,12 @@ status = "okay"; }; - gpiote: gpiote@4100a000 { + gpiote: gpiote0: gpiote@4100a000 { compatible = "nordic,nrf-gpiote"; reg = <0x4100a000 0x1000>; interrupts = <10 5>; status = "disabled"; + instance = <0>; }; wdt: wdt0: watchdog@4100b000 { @@ -317,6 +318,7 @@ #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; gpio1: gpio@418c0800 { @@ -327,6 +329,7 @@ ngpios = <16>; status = "disabled"; port = <1>; + gpiote-instance = <&gpiote>; }; }; diff --git a/dts/arm/nordic/nrf91.dtsi b/dts/arm/nordic/nrf91.dtsi index d166059c01d1518..81be475d7759700 100644 --- a/dts/arm/nordic/nrf91.dtsi +++ b/dts/arm/nordic/nrf91.dtsi @@ -59,11 +59,26 @@ status = "okay"; }; - gpiote: gpiote@5000d000 { + /* + * GPIOTE0 is always accessible as a secure peripheral, + * so we give it the 'gpiote' label for use when building + * code for this target. + */ + gpiote: gpiote0: gpiote@5000d000 { compatible = "nordic,nrf-gpiote"; reg = <0x5000d000 0x1000>; interrupts = <13 5>; status = "disabled"; + instance = <0>; + }; + + /* Additional Non-Secure GPIOTE instance */ + gpiote1: gpiote@40031000 { + compatible = "nordic,nrf-gpiote"; + reg = <0x40031000 0x1000>; + interrupts = <49 5>; + status = "disabled"; + instance = <1>; }; spu: spu@50003000 { diff --git a/dts/arm/nordic/nrf91_peripherals.dtsi b/dts/arm/nordic/nrf91_peripherals.dtsi index d6078e79120b6a0..b6ed30990be39dd 100644 --- a/dts/arm/nordic/nrf91_peripherals.dtsi +++ b/dts/arm/nordic/nrf91_peripherals.dtsi @@ -313,6 +313,7 @@ gpio0: gpio@842500 { #gpio-cells = <2>; status = "disabled"; port = <0>; + gpiote-instance = <&gpiote>; }; rtc0: rtc@14000 { diff --git a/dts/arm/nordic/nrf91ns.dtsi b/dts/arm/nordic/nrf91ns.dtsi index cff60f5f3c6298a..22510b0cfac45b6 100644 --- a/dts/arm/nordic/nrf91ns.dtsi +++ b/dts/arm/nordic/nrf91ns.dtsi @@ -45,12 +45,17 @@ #include "nrf91_peripherals.dtsi" }; - /* Additional Non-Secure peripherals */ - gpiote: gpiote@40031000 { + /* + * GPIOTE1 is always accessible as a non-secure peripheral, + * so we give it the 'gpiote' label for use when building + * code for this target. + */ + gpiote: gpiote1: gpiote@40031000 { compatible = "nordic,nrf-gpiote"; reg = <0x40031000 0x1000>; interrupts = <49 5>; status = "disabled"; + instance = <1>; }; }; diff --git a/dts/arm/nuvoton/m46x.dtsi b/dts/arm/nuvoton/m46x.dtsi index 03e62e817ea3ea4..d73a888d21b4019 100644 --- a/dts/arm/nuvoton/m46x.dtsi +++ b/dts/arm/nuvoton/m46x.dtsi @@ -436,7 +436,7 @@ reg = <0x40020000 0x200>, <0x40020200 0x1800>; reg-names = "m_can", "message_ram"; interrupts = <112 0>, <113 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; resets = <&rst NUMAKER_CANFD0_RST>; clocks = <&pcc NUMAKER_CANFD0_MODULE NUMAKER_CLK_CLKSEL0_CANFD0SEL_HCLK @@ -452,7 +452,7 @@ reg = <0x40024000 0x200>, <0x40024200 0x1800>; reg-names = "m_can", "message_ram"; interrupts = <114 0>, <115 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; resets = <&rst NUMAKER_CANFD1_RST>; clocks = <&pcc NUMAKER_CANFD1_MODULE NUMAKER_CLK_CLKSEL0_CANFD1SEL_HCLK @@ -468,7 +468,7 @@ reg = <0x40028000 0x200>, <0x40028200 0x1800>; reg-names = "m_can", "message_ram"; interrupts = <120 0>, <121 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; resets = <&rst NUMAKER_CANFD2_RST>; clocks = <&pcc NUMAKER_CANFD2_MODULE NUMAKER_CLK_CLKSEL0_CANFD2SEL_HCLK @@ -484,7 +484,7 @@ reg = <0x4002c000 0x200>, <0x4002c200 0x1800>; reg-names = "m_can", "message_ram"; interrupts = <122 0>, <123 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; resets = <&rst NUMAKER_CANFD3_RST>; clocks = <&pcc NUMAKER_CANFD3_MODULE NUMAKER_CLK_CLKSEL0_CANFD3SEL_HCLK diff --git a/dts/arm/nuvoton/npcx/npcx4.dtsi b/dts/arm/nuvoton/npcx/npcx4.dtsi index 5cc63cb658ee5a2..004ca5332afeaa1 100644 --- a/dts/arm/nuvoton/npcx/npcx4.dtsi +++ b/dts/arm/nuvoton/npcx/npcx4.dtsi @@ -289,7 +289,7 @@ clocks = <&pcc NPCX_CLOCK_BUS_FIU0 NPCX_PWDWN_CTL8 6>; }; - sha0: sha@13c { + sha0: sha@148 { compatible = "nuvoton,npcx-sha"; reg = <0x148 0x4c>; context-buffer-size = <240>; diff --git a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi index b7a13229e0015a8..c579a9176984ef8 100644 --- a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi @@ -220,6 +220,7 @@ compatible = "nxp,lpc-mcan"; reg = <0x9d000 0x1000>; interrupts = <43 0>, <44 0>; + interrupt-names = "int0", "int1"; clocks = <&syscon MCUX_MCAN_CLK>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; sample-point = <875>; diff --git a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi index 8a62b6fe5af4aae..304bf2e68d9474e 100644 --- a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi @@ -215,6 +215,7 @@ compatible = "nxp,lpc-mcan"; reg = <0x9d000 0x1000>; interrupts = <43 0>, <44 0>; + interrupt-names = "int0", "int1"; clocks = <&syscon MCUX_MCAN_CLK>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; sample-point = <875>; diff --git a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi index 348b5e6083d376b..18ca28d03e8457a 100644 --- a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi @@ -325,6 +325,7 @@ compatible = "nxp,lpc-mcan"; reg = <0x4009d000 0x1000>; interrupts = <43 0>, <44 0>; + interrupt-names = "int0", "int1"; clocks = <&syscon MCUX_MCAN_CLK>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; sample-point = <875>; diff --git a/dts/arm/nxp/nxp_s32k146.dtsi b/dts/arm/nxp/nxp_s32k146.dtsi index b875f09ce65e06e..bfbb1558349a3ca 100644 --- a/dts/arm/nxp/nxp_s32k146.dtsi +++ b/dts/arm/nxp/nxp_s32k146.dtsi @@ -34,6 +34,8 @@ }; /delete-node/ &lpi2c1; +/delete-node/ &ftm6; +/delete-node/ &ftm7; &nvic { arm,num-irq-priority-bits = <4>; @@ -59,3 +61,20 @@ &lpspi2 { clocks = <&clock NXP_S32_LPSPI2_CLK>; }; + +&flexcan0 { + interrupts = <78 0>, <79 0>, <80 0>, <81 0>, <82 0>; + interrupt-names = "warning", "error", "wake-up", "mb-0-15", "mb-16-31"; +}; + +&flexcan1 { + interrupts = <85 0>, <86 0>, <88 0>, <89 0>; + interrupt-names = "warning", "error", "mb-0-15", "mb-16-31"; + clocks = <&clock NXP_S32_FLEXCAN1_CLK>; +}; + +&flexcan2 { + interrupts = <92 0>, <93 0>, <95 0>; + interrupt-names = "warning", "error", "mb-0-15"; + clocks = <&clock NXP_S32_FLEXCAN2_CLK>; +}; diff --git a/dts/arm/nxp/nxp_s32k1xx.dtsi b/dts/arm/nxp/nxp_s32k1xx.dtsi index 5a5a32fefa665a4..a8c07d14028163b 100644 --- a/dts/arm/nxp/nxp_s32k1xx.dtsi +++ b/dts/arm/nxp/nxp_s32k1xx.dtsi @@ -44,6 +44,28 @@ status = "disabled"; }; + flexcan0: can@40024000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x40024000 0x1000>; + clocks = <&clock NXP_S32_FLEXCAN0_CLK>; + clk-source = <1>; + status = "disabled"; + }; + + flexcan1: can@40025000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x40025000 0x1000>; + clk-source = <1>; + status = "disabled"; + }; + + flexcan2: can@4002b000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x4002b000 0x1000>; + clk-source = <1>; + status = "disabled"; + }; + lpspi0: spi@4002c000 { compatible = "nxp,imx-lpspi"; reg = <0x4002c000 0x1000>; @@ -202,5 +224,85 @@ nxp,kinetis-port = <&porte>; status = "disabled"; }; + + ftm0: ftm@40038000 { + compatible = "nxp,kinetis-ftm"; + reg = <0x40038000 0x1000>; + interrupts = <99 0>, <100 0>, <101 0>, <102 0>, <104 0>; + interrupt-names = "0-1", "2-3", "4-5", "6-7", "overflow"; + clocks = <&clock NXP_S32_RTC_CLK>; + prescaler = <1>; + status = "disabled"; + }; + + ftm1: ftm@40039000 { + compatible = "nxp,kinetis-ftm"; + reg = <0x40039000 0x1000>; + interrupts = <105 0>, <106 0>, <107 0>, <108 0>, <110 0>; + interrupt-names = "0-1", "2-3", "4-5", "6-7", "overflow"; + clocks = <&clock NXP_S32_RTC_CLK>; + prescaler = <1>; + status = "disabled"; + }; + + ftm2: ftm@4003a000 { + compatible = "nxp,kinetis-ftm"; + reg = <0x4003a000 0x1000>; + interrupts = <111 0>, <112 0>, <113 0>, <114 0>, <116 0>; + interrupt-names = "0-1", "2-3", "4-5", "6-7", "overflow"; + clocks = <&clock NXP_S32_RTC_CLK>; + prescaler = <1>; + status = "disabled"; + }; + + ftm3: ftm@40026000 { + compatible = "nxp,kinetis-ftm"; + reg = <0x40026000 0x1000>; + interrupts = <117 0>, <118 0>, <119 0>, <120 0>, <122 0>; + interrupt-names = "0-1", "2-3", "4-5", "6-7", "overflow"; + clocks = <&clock NXP_S32_RTC_CLK>; + prescaler = <1>; + status = "disabled"; + }; + + ftm4: ftm@4006e000 { + compatible = "nxp,kinetis-ftm"; + reg = <0x4006e000 0x1000>; + interrupts = <123 0>, <124 0>, <125 0>, <126 0>, <128 0>; + interrupt-names = "0-1", "2-3", "4-5", "6-7", "overflow"; + clocks = <&clock NXP_S32_RTC_CLK>; + prescaler = <1>; + status = "disabled"; + }; + + ftm5: ftm@4006f000 { + compatible = "nxp,kinetis-ftm"; + reg = <0x4006f000 0x1000>; + interrupts = <129 0>, <130 0>, <131 0>, <132 0>, <134 0>; + interrupt-names = "0-1", "2-3", "4-5", "6-7", "overflow"; + clocks = <&clock NXP_S32_RTC_CLK>; + prescaler = <1>; + status = "disabled"; + }; + + ftm6: ftm@40070000 { + compatible = "nxp,kinetis-ftm"; + reg = <0x40070000 0x1000>; + interrupts = <135 0>, <136 0>, <137 0>, <138 0>, <140 0>; + interrupt-names = "0-1", "2-3", "4-5", "6-7", "overflow"; + clocks = <&clock NXP_S32_RTC_CLK>; + prescaler = <1>; + status = "disabled"; + }; + + ftm7: ftm@40071000 { + compatible = "nxp,kinetis-ftm"; + reg = <0x40071000 0x1000>; + interrupts = <141 0>, <142 0>, <143 0>, <144 0>, <146 0>; + interrupt-names = "0-1", "2-3", "4-5", "6-7", "overflow"; + clocks = <&clock NXP_S32_RTC_CLK>; + prescaler = <1>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/renesas/ra/ra-cm4-common.dtsi b/dts/arm/renesas/ra/ra-cm4-common.dtsi index 80e2f877c8ab4fe..4ef18141e6c44e2 100644 --- a/dts/arm/renesas/ra/ra-cm4-common.dtsi +++ b/dts/arm/renesas/ra/ra-cm4-common.dtsi @@ -247,7 +247,7 @@ }; sci0: sci@40070000 { - compatible = "renesas,ra-uart-sci"; + compatible = "renesas,ra-sci"; reg = <0x40070000 0x20>; interrupts = , , @@ -266,7 +266,7 @@ }; sci1: sci@40070020 { - compatible = "renesas,ra-uart-sci"; + compatible = "renesas,ra-sci"; reg = <0x40070020 0x20>; interrupts = , , @@ -284,7 +284,7 @@ }; sci9: sci@40070120 { - compatible = "renesas,ra-uart-sci"; + compatible = "renesas,ra-sci"; reg = <0x40070120 0x20>; interrupts = , , diff --git a/dts/arm/st/g0/stm32g0b1.dtsi b/dts/arm/st/g0/stm32g0b1.dtsi index ead49eb060522a5..28b55fc70de67d6 100644 --- a/dts/arm/st/g0/stm32g0b1.dtsi +++ b/dts/arm/st/g0/stm32g0b1.dtsi @@ -35,7 +35,7 @@ reg = <0x40006400 0x400>, <0x4000b400 0x350>; reg-names = "m_can", "message_ram"; interrupts = <21 0>, <22 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00001000>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; sample-point = <875>; diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index 1b6632f694f4870..d42ff353a731bc8 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -387,7 +387,7 @@ reg = <0x40006400 0x400>, <0x4000a400 0x350>; reg-names = "m_can", "message_ram"; interrupts = <21 0>, <22 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; sample-point = <875>; diff --git a/dts/arm/st/g4/stm32g473.dtsi b/dts/arm/st/g4/stm32g473.dtsi index 930e163979501bd..0cdcc317f0a68b8 100644 --- a/dts/arm/st/g4/stm32g473.dtsi +++ b/dts/arm/st/g4/stm32g473.dtsi @@ -100,7 +100,7 @@ reg = <0x40006c00 0x400>, <0x4000a400 0x9f0>; reg-names = "m_can", "message_ram"; interrupts = <88 0>, <89 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; bosch,mram-cfg = <0x6a0 28 8 3 3 0 3 3>; sample-point = <875>; diff --git a/dts/arm/st/g4/stm32g491.dtsi b/dts/arm/st/g4/stm32g491.dtsi index 865d3700d96963a..1e616accc776e4c 100644 --- a/dts/arm/st/g4/stm32g491.dtsi +++ b/dts/arm/st/g4/stm32g491.dtsi @@ -15,7 +15,7 @@ reg = <0x40006800 0x400>, <0x4000a400 0x6a0>; reg-names = "m_can", "message_ram"; interrupts = <86 0>, <87 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>; sample-point = <875>; diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index 310b3384f602978..dff30f083da6703 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -438,7 +438,7 @@ reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; reg-names = "m_can", "message_ram"; interrupts = <39 0>, <40 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; sample-point = <875>; diff --git a/dts/arm/st/h5/stm32h562.dtsi b/dts/arm/st/h5/stm32h562.dtsi index 6d99b0d67e29024..1285f10b1ebe253 100644 --- a/dts/arm/st/h5/stm32h562.dtsi +++ b/dts/arm/st/h5/stm32h562.dtsi @@ -308,7 +308,7 @@ reg = <0x4000a800 0x400>, <0x4000ac00 0x6a0>; reg-names = "m_can", "message_ram"; interrupts = <109 0>, <110 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; /* common clock FDCAN 1 & 2 */ clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>; diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index 9dcd1353132317d..64ccfbf7241ae76 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -466,13 +466,55 @@ status = "disabled"; }; + i2s1: i2s@40013000 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40013000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>, + <&rcc STM32_SRC_PLL1_Q SPI123_SEL(0)>; + dmas = <&dmamux1 0 38 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH) + &dmamux1 1 37 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>; + dma-names = "tx", "rx"; + interrupts = <35 3>; + status = "disabled"; + }; + + i2s2: i2s@40003800 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>, + <&rcc STM32_SRC_PLL1_Q SPI123_SEL(0)>; + dmas = <&dmamux1 0 40 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH) + &dmamux1 1 39 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>; + dma-names = "tx", "rx"; + interrupts = <36 0>; + status = "disabled"; + }; + + i2s3: i2s@40003c00 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00008000>, + <&rcc STM32_SRC_PLL1_Q SPI123_SEL(0)>; + dmas = <&dmamux1 0 62 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH) + &dmamux1 1 61 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>; + dma-names = "tx", "rx"; + interrupts = <51 0>; + status = "disabled"; + }; + fdcan1: can@4000a000 { compatible = "st,stm32h7-fdcan"; reg = <0x4000a000 0x400>, <0x4000ac00 0x350>; reg-names = "m_can", "message_ram"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; interrupts = <19 0>, <21 0>, <63 0>; - interrupt-names = "LINE_0", "LINE_1", "CALIB"; + interrupt-names = "int0", "int1", "calib"; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; sample-point = <875>; sample-point-data = <875>; @@ -485,7 +527,7 @@ reg-names = "m_can", "message_ram"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; interrupts = <20 0>, <22 0>, <63 0>; - interrupt-names = "LINE_0", "LINE_1", "CALIB"; + interrupt-names = "int0", "int1", "calib"; bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>; sample-point = <875>; sample-point-data = <875>; diff --git a/dts/arm/st/h7/stm32h723.dtsi b/dts/arm/st/h7/stm32h723.dtsi index f1b0836f6e83007..1a2b917bc1e01f8 100644 --- a/dts/arm/st/h7/stm32h723.dtsi +++ b/dts/arm/st/h7/stm32h723.dtsi @@ -121,7 +121,7 @@ reg-names = "m_can", "message_ram"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; interrupts = <159 0>, <160 0>, <63 0>; - interrupt-names = "LINE_0", "LINE_1", "CALIB"; + interrupt-names = "int0", "int1", "calib"; bosch,mram-cfg = <0x6a0 28 8 3 3 0 3 3>; sample-point = <875>; sample-point-data = <875>; diff --git a/dts/arm/st/h7/stm32h7a3.dtsi b/dts/arm/st/h7/stm32h7a3.dtsi index 7f85387ca06e662..8ff4353855ae0e2 100644 --- a/dts/arm/st/h7/stm32h7a3.dtsi +++ b/dts/arm/st/h7/stm32h7a3.dtsi @@ -79,6 +79,19 @@ status = "disabled"; }; + i2s6: i2s@58001400 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x58001400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00000020>, + <&rcc STM32_SRC_PLL1_Q SPI6_SEL(0)>; + dmas = <&dmamux2 0 12 0x20440 &dmamux2 1 11 0x20480>; + dma-names = "tx", "rx"; + interrupts = <86 0>; + status = "disabled"; + }; + rng: rng@48021800 { nist-config = <0xf00d00>; health-test-magic = <0x17590abc>; diff --git a/dts/arm/st/u5/stm32u5.dtsi b/dts/arm/st/u5/stm32u5.dtsi index b97e509c8315a59..f721617ef5bba83 100644 --- a/dts/arm/st/u5/stm32u5.dtsi +++ b/dts/arm/st/u5/stm32u5.dtsi @@ -798,7 +798,7 @@ reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; reg-names = "m_can", "message_ram"; interrupts = <39 0>, <40 0>; - interrupt-names = "LINE_0", "LINE_1"; + interrupt-names = "int0", "int1"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; sample-point = <875>; diff --git a/dts/arm64/nxp/nxp_mimx93_a55.dtsi b/dts/arm64/nxp/nxp_mimx93_a55.dtsi index 22a61e2dfca8488..bfedef483815ded 100644 --- a/dts/arm64/nxp/nxp_mimx93_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx93_a55.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include / { #address-cells = <1>; @@ -94,4 +95,188 @@ clocks = <&ccm IMX_CCM_LPUART2_CLK 0x6c 24>; status = "disabled"; }; + + lpi2c1: i2c@44340000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x44340000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_LPI2C1_CLK 0x70 6>; + status = "disabled"; + }; + + lpi2c2: i2c@44350000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x44350000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_LPI2C2_CLK 0x70 8>; + status = "disabled"; + }; + + lpi2c3: i2c@42530000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x42530000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_LPI2C3_CLK 0x70 10>; + status = "disabled"; + }; + + lpi2c4: i2c@42540000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x42540000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_LPI2C4_CLK 0x80 24>; + status = "disabled"; + }; + + lpi2c5: i2c@426b0000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x426b0000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_LPI2C5_CLK 0x80 24>; + status = "disabled"; + }; + + lpi2c6: i2c@426c0000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x426c0000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_LPI2C6_CLK 0x80 24>; + status = "disabled"; + }; + + lpi2c7: i2c@426d0000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x426d0000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_LPI2C7_CLK 0x80 24>; + status = "disabled"; + }; + + lpi2c8: i2c@426e0000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x426e0000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_LPI2C8_CLK 0x80 24>; + status = "disabled"; + }; + + lpspi1: spi@44360000 { + compatible = "nxp,imx-lpspi"; + reg = <0x44360000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "disabled"; + clocks = <&ccm IMX_CCM_LPSPI1_CLK 0x6c 0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + lpspi2: spi@44370000 { + compatible = "nxp,imx-lpspi"; + reg = <0x44370000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "disabled"; + clocks = <&ccm IMX_CCM_LPSPI2_CLK 0x6c 2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + lpspi3: spi@42550000 { + compatible = "nxp,imx-lpspi"; + reg = <0x42550000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "disabled"; + clocks = <&ccm IMX_CCM_LPSPI3_CLK 0x6c 4>; + #address-cells = <1>; + #size-cells = <0>; + }; + + lpspi4: spi@42560000 { + compatible = "nxp,imx-lpspi"; + reg = <0x42560000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "disabled"; + clocks = <&ccm IMX_CCM_LPSPI4_CLK 0x6c 6>; + #address-cells = <1>; + #size-cells = <0>; + }; + + lpspi5: spi@426f0000 { + compatible = "nxp,imx-lpspi"; + reg = <0x426f0000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "disabled"; + clocks = <&ccm IMX_CCM_LPSPI5_CLK 0x6c 6>; + #address-cells = <1>; + #size-cells = <0>; + }; + + lpspi6: spi@42700000 { + compatible = "nxp,imx-lpspi"; + reg = <0x42700000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "disabled"; + clocks = <&ccm IMX_CCM_LPSPI6_CLK 0x6c 6>; + #address-cells = <1>; + #size-cells = <0>; + }; + + lpspi7: spi@42710000 { + compatible = "nxp,imx-lpspi"; + reg = <0x42710000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "disabled"; + clocks = <&ccm IMX_CCM_LPSPI7_CLK 0x6c 0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + lpspi8: spi@42720000 { + compatible = "nxp,imx-lpspi"; + reg = <0x42720000 0x4000>; + interrupts = ; + interrupt-parent = <&gic>; + status = "disabled"; + clocks = <&ccm IMX_CCM_LPSPI8_CLK 0x6c 2>; + #address-cells = <1>; + #size-cells = <0>; + }; }; diff --git a/dts/bindings/adc/ti,lmp90xxx-base.yaml b/dts/bindings/adc/ti,lmp90xxx-base.yaml index 4225c9b0cc347c2..8c0bb066b8028f6 100644 --- a/dts/bindings/adc/ti,lmp90xxx-base.yaml +++ b/dts/bindings/adc/ti,lmp90xxx-base.yaml @@ -10,8 +10,7 @@ properties: description: Data Ready Bar "#io-channel-cells": - const: 2 + const: 1 io-channel-cells: - - positive - - negative + - input diff --git a/dts/bindings/bluetooth/st,hci-spi-v1.yaml b/dts/bindings/bluetooth/st,hci-spi-v1.yaml index d61b936c5b645d1..3784c88ded047cb 100644 --- a/dts/bindings/bluetooth/st,hci-spi-v1.yaml +++ b/dts/bindings/bluetooth/st,hci-spi-v1.yaml @@ -4,3 +4,5 @@ description: STMicroelectronics SPI protocol V1 compatible with BlueNRG-MS devices compatible: "st,hci-spi-v1" + +include: zephyr,bt-hci-spi.yaml diff --git a/dts/bindings/bluetooth/st,hci-spi-v2.yaml b/dts/bindings/bluetooth/st,hci-spi-v2.yaml index 58e91e496e213a0..36b25eae768946d 100644 --- a/dts/bindings/bluetooth/st,hci-spi-v2.yaml +++ b/dts/bindings/bluetooth/st,hci-spi-v2.yaml @@ -4,3 +4,5 @@ description: STMicroelectronics SPI protocol V2 compatible with BlueNRG-1 and successor devices compatible: "st,hci-spi-v2" + +include: zephyr,bt-hci-spi.yaml diff --git a/dts/bindings/can/atmel,sam-can.yaml b/dts/bindings/can/atmel,sam-can.yaml index e693000919458ae..c224604fa0bd9c1 100644 --- a/dts/bindings/can/atmel,sam-can.yaml +++ b/dts/bindings/can/atmel,sam-can.yaml @@ -13,6 +13,9 @@ properties: interrupts: required: true + interrupt-names: + required: true + clocks: required: true diff --git a/dts/bindings/can/atmel,sam0-can.yaml b/dts/bindings/can/atmel,sam0-can.yaml index 486620a21b7bb42..7002386c9228da9 100644 --- a/dts/bindings/can/atmel,sam0-can.yaml +++ b/dts/bindings/can/atmel,sam0-can.yaml @@ -13,6 +13,9 @@ properties: interrupts: required: true + interrupt-names: + required: true + clocks: required: true diff --git a/dts/bindings/can/nuvoton,numaker-canfd.yaml b/dts/bindings/can/nuvoton,numaker-canfd.yaml index e3d28f5ce28a806..f70e86693c16216 100644 --- a/dts/bindings/can/nuvoton,numaker-canfd.yaml +++ b/dts/bindings/can/nuvoton,numaker-canfd.yaml @@ -14,6 +14,9 @@ properties: interrupts: required: true + interrupt-names: + required: true + resets: required: true diff --git a/dts/bindings/can/nxp,lpc-mcan.yaml b/dts/bindings/can/nxp,lpc-mcan.yaml index a17b0132e62ef41..48aef0031396c81 100644 --- a/dts/bindings/can/nxp,lpc-mcan.yaml +++ b/dts/bindings/can/nxp,lpc-mcan.yaml @@ -11,5 +11,8 @@ properties: interrupts: required: true + interrupt-names: + required: true + clocks: required: true diff --git a/dts/bindings/can/st,stm32-fdcan.yaml b/dts/bindings/can/st,stm32-fdcan.yaml index d950bb4e92493e7..f4cfb310dac60f9 100644 --- a/dts/bindings/can/st,stm32-fdcan.yaml +++ b/dts/bindings/can/st,stm32-fdcan.yaml @@ -11,6 +11,9 @@ properties: interrupts: required: true + interrupt-names: + required: true + clocks: required: true diff --git a/dts/bindings/can/st,stm32h7-fdcan.yaml b/dts/bindings/can/st,stm32h7-fdcan.yaml index 3cee6e29219a7b7..1d258ea4abfaf76 100644 --- a/dts/bindings/can/st,stm32h7-fdcan.yaml +++ b/dts/bindings/can/st,stm32h7-fdcan.yaml @@ -13,3 +13,6 @@ properties: interrupts: required: true + + interrupt-names: + required: true diff --git a/dts/bindings/charger/ti,bq25180.yaml b/dts/bindings/charger/ti,bq25180.yaml new file mode 100644 index 000000000000000..be3b336aa50e9b4 --- /dev/null +++ b/dts/bindings/charger/ti,bq25180.yaml @@ -0,0 +1,30 @@ +# Copyright 2024 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: | + BQ25180 I2C Controlled, 1-Cell, 1-A Linear Battery Charger with Power Path + and Ship Mode. + + The device has a single child node for the charger. For example: + + bq25180@6a { + compatible = "ti,bq25180"; + reg = <0x6a>; + + constant-charge-current-max-microamp = <500000>; + }; + +compatible: "ti,bq25180" + +include: [battery.yaml, i2c-device.yaml] + + +properties: + constant-charge-current-max-microamp: + type: int + default: 0 + description: | + Charge current set at init time in uA, available range is 5 mA to 800 mA. + The value specified will be rounded down to the closest implemented + value. If set to 0 (default) skip setting the charge current value at + driver initialization. diff --git a/dts/bindings/clock/st,stm32f4-pll-clock.yaml b/dts/bindings/clock/st,stm32f4-pll-clock.yaml index 137a15822ac3a04..1346ec8a55fd45b 100644 --- a/dts/bindings/clock/st,stm32f4-pll-clock.yaml +++ b/dts/bindings/clock/st,stm32f4-pll-clock.yaml @@ -61,3 +61,10 @@ properties: Main PLL (PLL) division factor for USB OTG FS, SDMMC and random number generator clocks. Valid range: 2 - 15 + + div-r: + type: int + description: | + Main PLL (PLL) division factor for I2S and DFSDM + generator clocks. + Valid range: 2 - 7 diff --git a/dts/bindings/ethernet/infineon,xmc4xxx-ethernet.yaml b/dts/bindings/ethernet/infineon,xmc4xxx-ethernet.yaml new file mode 100644 index 000000000000000..c526fe89055e3f5 --- /dev/null +++ b/dts/bindings/ethernet/infineon,xmc4xxx-ethernet.yaml @@ -0,0 +1,118 @@ +# Copyright (c) 2023 SLB +# SPDX-License-Identifier: Apache-2.0 + +description: XMC 4XXX Ethernet + +compatible: "infineon,xmc4xxx-ethernet" + +include: + - name: ethernet-controller.yaml + - name: pinctrl-device.yaml + +properties: + interrupts: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + phy-connection-type: + required: true + + rxd0-port-ctrl: + required: true + type: string + description: Receive bit 0 (rxd0) signal GPIO connection. Used for RMII and MII interfaces. + enum: + - "P2_2" + - "P0_2" + - "P14_8" + - "P5_0" + + rxd1-port-ctrl: + required: true + type: string + description: Receive bit 1 (rxd1) signal GPIO connection. Used for RMII and MII interfaces. + enum: + - "P2_3" + - "P0_3" + - "P14_9" + - "P5_1" + + rxd2-port-ctrl: + type: string + description: Receive bit 2 (rxd2) signal GPIO connection. Only used for MII interface. + enum: + - "P5_8" + - "P6_4" + + rxd3-port-ctrl: + type: string + description: Receive bit 2 (rxd2) signal GPIO connection. Only used for MII interface. + enum: + - "P5_9" + - "P6_3" + + rmii-rx-clk-port-ctrl: + required: true + description: | + If the RMII interface is used it connects GPIO to the rmii-clk signal. + Otherwise, if the MII interface is used, then it connects to the Receive clock (rx-clk) + signal. + type: string + enum: + - "P2_1" + - "P0_0" + - "P15_8" + - "P6_5" + + crs-rx-dv-port-ctrl: + required: true + description: | + If the RMII interface is used it connects GPIO to the Carrier Sense Data Valid (crs-dv) + signal. Otherwise, if the MII interface is used, it connects to the + Receive Data Valid (rx-dv) signal. + type: string + enum: + - "P2_5" + - "P0_1" + - "P15_9" + - "P5_2" + + crs-port-ctrl: + description: Carrier Sense (crs) signal GPIO connection. Only used for the MII interface. + type: string + enum: + - "P5_11" + - "unused1" + - "unused2" + - "P5_4" + + rxer-port-ctrl: + required: true + description: Receive Error (rxer) signal GPIO connection. Used for MII and RMII interfaces. + type: string + enum: + - "P2_4" + - "P0_11" + - "unused1" + - "P5_3" + + col-port-ctrl: + description: Collision (col) signal GPIO connection. Only used for MII interface. + type: string + enum: + - "P2_15" + - "unused1" + - "unused2" + - "P5_5" + + tx-clk-port-ctrl: + description: Transmit clock (tx-clk) GPIO connection. Only used for MII interface. + type: string + enum: + - "P5_10" + - "P6_6" diff --git a/dts/bindings/gpio/nordic,nrf-gpio.yaml b/dts/bindings/gpio/nordic,nrf-gpio.yaml index 550acd1a865cfe8..097a99d8fa94b0f 100644 --- a/dts/bindings/gpio/nordic,nrf-gpio.yaml +++ b/dts/bindings/gpio/nordic,nrf-gpio.yaml @@ -11,6 +11,11 @@ properties: reg: required: true + gpiote-instance: + type: phandle + description: | + GPIOTE instance that can be used with this GPIO port. + "#gpio-cells": const: 2 diff --git a/dts/bindings/gpio/nordic,nrf-gpiote.yaml b/dts/bindings/gpio/nordic,nrf-gpiote.yaml index 49ddba3595ba42f..cefc3385afef8b2 100644 --- a/dts/bindings/gpio/nordic,nrf-gpiote.yaml +++ b/dts/bindings/gpio/nordic,nrf-gpiote.yaml @@ -13,3 +13,15 @@ properties: interrupts: required: true + + instance: + type: int + required: true + description: | + The GPIOTE instance number. GPIOTE instance GPIOTE0 has: + + instance = <0>; + + And GPIOTE1 has: + + instance = <1>; diff --git a/dts/bindings/i2s/st,stm32-i2s-common.yaml b/dts/bindings/i2s/st,stm32-i2s-common.yaml new file mode 100644 index 000000000000000..09e13c449e9a84e --- /dev/null +++ b/dts/bindings/i2s/st,stm32-i2s-common.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2018, STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +# Common fields for STM32 I2S peripherals. + +include: [i2s-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + dmas: + required: true + + dma-names: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + mck-enabled: + type: boolean + description: | + Master Clock Output function. + An mck pin must be listed within pinctrl-0 when enabling this property. diff --git a/dts/bindings/i2s/st,stm32-i2s.yaml b/dts/bindings/i2s/st,stm32-i2s.yaml index 1de415d0ddf9d67..263e787d4659f94 100644 --- a/dts/bindings/i2s/st,stm32-i2s.yaml +++ b/dts/bindings/i2s/st,stm32-i2s.yaml @@ -5,29 +5,4 @@ description: STM32 I2S controller compatible: "st,stm32-i2s" -include: [i2s-controller.yaml, pinctrl-device.yaml] - -properties: - reg: - required: true - - interrupts: - required: true - - dmas: - required: true - - dma-names: - required: true - - pinctrl-0: - required: true - - pinctrl-names: - required: true - - mck-enabled: - type: boolean - description: | - Master Clock Output function. - An mck pin must be listed within pinctrl-0 when enabling this property. +include: st,stm32-i2s-common.yaml diff --git a/dts/bindings/i2s/st,stm32h7-i2s.yaml b/dts/bindings/i2s/st,stm32h7-i2s.yaml new file mode 100644 index 000000000000000..8fa3bf89c5b1c39 --- /dev/null +++ b/dts/bindings/i2s/st,stm32h7-i2s.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2018, STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: STM32H7 I2S controller + +compatible: "st,stm32h7-i2s" + +include: st,stm32-i2s-common.yaml diff --git a/dts/bindings/input/analog-axis.yaml b/dts/bindings/input/analog-axis.yaml new file mode 100644 index 000000000000000..ded94e86c0f2426 --- /dev/null +++ b/dts/bindings/input/analog-axis.yaml @@ -0,0 +1,90 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: | + ADC based analog axis input device + + Implement an input device generating absolute axis events by periodically + reading from some ADC channels. + + Example configuration: + + #include + + analog_axis { + compatible = "analog-axis"; + poll-period-ms = <15>; + axis-x { + io-channels = <&adc 0>; + out-deadzone = <8>; + in-min = <100>; + in-max = <800>; + zephyr,axis = ; + }; + }; + +compatible: "analog-axis" + +include: base.yaml + +properties: + poll-period-ms: + type: int + default: 15 + description: | + How often to get new ADC samples for the various configured axes in + milliseconds. Defaults to 15ms if unspecified. + +child-binding: + properties: + io-channels: + type: phandle-array + required: true + description: | + ADC IO channel to use. + + out-min: + type: int + default: 0 + description: | + Minimum value to output on input events. Defaults to 0 if unspecified. + + out-max: + type: int + default: 255 + description: | + Maximum value to output on input events. Defaults to 255 if + unspecified. + + out-deadzone: + type: int + default: 0 + description: | + Deadzone for the output center value. If specified output values + between the center of the range plus or minus this value will be + reported as center. Defaults to 0, no deadzone. + + in-min: + type: int + required: true + description: | + Input value that corresponds to the minimum output value. + + in-max: + type: int + required: true + description: | + Input value that corresponds to the maximum output value. + + zephyr,axis: + type: int + required: true + description: | + The input code for the axis to report for the device, typically any of + INPUT_ABS_*. + + invert: + type: boolean + description: | + If set, invert the raw ADC value before processing it. Useful for + differential channels. diff --git a/dts/bindings/input/gpio-keys.yaml b/dts/bindings/input/gpio-keys.yaml index 9b3581a1c13cb92..f2776bbda9d8079 100644 --- a/dts/bindings/input/gpio-keys.yaml +++ b/dts/bindings/input/gpio-keys.yaml @@ -35,15 +35,23 @@ properties: Debouncing interval time in milliseconds. If not specified defaults to 30. + polling-mode: + type: boolean + description: | + Do not use interrupts for the key GPIOs, poll the pin periodically at the + specified debounce-interval-ms instead. + child-binding: description: GPIO KEYS child node properties: gpios: type: phandle-array required: true + label: type: string description: Descriptive name of the key + zephyr,code: type: int description: Key code to emit. diff --git a/dts/bindings/led_strip/worldsemi,ws2812-rpi_pico-pio.yaml b/dts/bindings/led_strip/worldsemi,ws2812-rpi_pico-pio.yaml new file mode 100644 index 000000000000000..d5d41ed38ee3962 --- /dev/null +++ b/dts/bindings/led_strip/worldsemi,ws2812-rpi_pico-pio.yaml @@ -0,0 +1,68 @@ +# Copyright (c) 2023, TOKITA Hiroshi +# SPDX-License-Identifier: Apache-2.0 + +description: | + The pio node configured for ws2812. + +compatible: "worldsemi,ws2812-rpi_pico-pio" + +include: pinctrl-device.yaml + +properties: + bit-waveform: + type: array + description: | + This property defines the waveform for sending 1-bit data. + The program uses the first three elements of the array. + The T0 is equal to T0H in the datasheet. + The T2 is equal to T1L in the datasheet. + The T1 is equal to (T1H-T0H) or (T0L-T1L) in the datasheet. + + Code-0 + +------+ +--- + | | | + | T0 | T1+T2 | + | | | + ---+ +-----------------+ + + Code-1 + +---------------+ +--- + | | | + | T0+T1 | T2 | + | | | + ---+ +--------+ + + + The frequency determines the wave period. + The T0~T2 means ratio in one period. + + For example, T0=3, T1=3, T2=4 and the frequency is 800kHz case, + T0H is + (1 / 800kHz) * (3/10) = 375ns + T0L is + (1 / 800kHz) * ((4+3)/10) = 875ns + +child-binding: + description: | + Worldsemi WS2812 or compatible LED strip driver based on RaspberryPi Pico's PIO + The LED strip node can put up to 4 instances under a single PIO node. + + include: ws2812.yaml + + properties: + output-pin: + type: int + required: true + description: | + Select the output pin. + + Note: This driver does not configure the output pin. + You need to configure the pin with pinctrl that is in the parent node configuration + for use by PIO. + + frequency: + type: int + description: | + Specify the number of times a waveform representing 1 bit is + transmitted per second. It is same meaning as bit-per-seconds. + WS2812 works with 800000. Set the value 400000 if use with WS2811. diff --git a/dts/bindings/mdio/infineon,xmc4xxx-mdio.yaml b/dts/bindings/mdio/infineon,xmc4xxx-mdio.yaml new file mode 100644 index 000000000000000..b9da5926d6bbd8a --- /dev/null +++ b/dts/bindings/mdio/infineon,xmc4xxx-mdio.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2023 SLB +# SPDX-License-Identifier: Apache-2.0 + +description: Infineon xmc4xxx Family MDIO Driver node + +compatible: "infineon,xmc4xxx-mdio" + +include: + - name: mdio-controller.yaml + - name: pinctrl-device.yaml + +properties: + mdi-port-ctrl: + description: | + The MDIO input is connected to several port/pins via a mux. + This is not handled by pinctrl because the mux is located at the + peripheral and not GPIO. The possible connections are defined by + an enum. + type: string + + enum: + - "P0_9" + - "P2_0" + - "P1_11" + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true diff --git a/dts/bindings/regulator/maxim,max20335-regulator.yaml b/dts/bindings/regulator/maxim,max20335-regulator.yaml index 44086e0c4fac9be..d23a1fdf1c1ef5c 100644 --- a/dts/bindings/regulator/maxim,max20335-regulator.yaml +++ b/dts/bindings/regulator/maxim,max20335-regulator.yaml @@ -40,10 +40,12 @@ child-binding: include: - name: regulator.yaml property-allowlist: - - regulator-always-on - - regulator-boot-on - - regulator-max-microamp + - regulator-init-microvolt - regulator-min-microvolt - regulator-max-microvolt - - regulator-allowed-modes + - regulator-init-microamp + - regulator-max-microamp + - regulator-always-on + - regulator-boot-on - regulator-initial-mode + - regulator-allowed-modes diff --git a/dts/bindings/regulator/regulator.yaml b/dts/bindings/regulator/regulator.yaml index 167355d92245b2d..635bfa49596d415 100644 --- a/dts/bindings/regulator/regulator.yaml +++ b/dts/bindings/regulator/regulator.yaml @@ -31,6 +31,10 @@ properties: type: int description: Offset applied to voltages to compensate for voltage drops + regulator-init-microamp: + type: int + description: Current set during initialisation + regulator-min-microamp: type: int description: smallest current consumers may set diff --git a/dts/bindings/usb/usb-audio-hp.yaml b/dts/bindings/usb/usb-audio-hp.yaml index 91968126c1e6865..a7b1f857d5ff50c 100644 --- a/dts/bindings/usb/usb-audio-hp.yaml +++ b/dts/bindings/usb/usb-audio-hp.yaml @@ -18,6 +18,12 @@ properties: - 16 - 24 - 32 + sample-rate-hz: + type: int + default: 48000 + polling-interval: + type: int + default: 1 # channel configuration options channel-l: type: boolean diff --git a/dts/bindings/usb/usb-audio-hs.yaml b/dts/bindings/usb/usb-audio-hs.yaml index ce0245cc1361ea0..e876746ebe30dee 100644 --- a/dts/bindings/usb/usb-audio-hs.yaml +++ b/dts/bindings/usb/usb-audio-hs.yaml @@ -30,6 +30,12 @@ properties: - "Asynchronous" - "Adaptive" - "Synchronous" + mic-sample-rate-hz: + type: int + default: 48000 + mic-polling-interval: + type: int + default: 1 hp-resolution: type: int default: 16 @@ -38,6 +44,12 @@ properties: - 16 - 24 - 32 + hp-sample-rate-hz: + type: int + default: 48000 + hp-polling-interval: + type: int + default: 1 # microphone channel configuration options mic-channel-l: type: boolean diff --git a/dts/bindings/usb/usb-audio-mic.yaml b/dts/bindings/usb/usb-audio-mic.yaml index 032021fd363a0a1..c8571084682cb0b 100644 --- a/dts/bindings/usb/usb-audio-mic.yaml +++ b/dts/bindings/usb/usb-audio-mic.yaml @@ -30,6 +30,12 @@ properties: - "Asynchronous" - "Adaptive" - "Synchronous" + sample-rate-hz: + type: int + default: 48000 + polling-interval: + type: int + default: 1 # channel configuration options channel-l: type: boolean diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 4096d5cad0d4be4..231fa50da0faa6b 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -512,6 +512,7 @@ rda Unisoc Communications, Inc. realtek Realtek Semiconductor Corp. remarkable reMarkable AS renesas Renesas Electronics Corporation +renode Antmicro's open source simulation and virtual development framework rex iMX6 Rex Project rervision Shenzhen Rervision Technology Co., Ltd. revotics Revolution Robotics, Inc. (Revotics) diff --git a/dts/bindings/w1/zephyr,w1-gpio.yaml b/dts/bindings/w1/zephyr,w1-gpio.yaml new file mode 100644 index 000000000000000..46f4e684e01b7a5 --- /dev/null +++ b/dts/bindings/w1/zephyr,w1-gpio.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2023 Hudson C. Dalpra +# SPDX-License-Identifier: Apache-2.0 + +description: | + Zephyr W1 GPIO node + + This defines a one-wire driver through GPIO bit-banging. + + For example: + + / { + w1: w1 { + compatible = "zephyr,w1-gpio"; + gpios = <&gpio0 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN | GPIO_PULL_UP)>; + }; + }; + + Above: + - w1 is pin 13 on gpio0. The gpio is active when the pin is high, is + configured as an open-drain, and has a pull-up resistor. + +compatible: "zephyr,w1-gpio" + +include: [w1-master.yaml] + +properties: + gpios: + type: phandle-array + required: true diff --git a/dts/riscv/renode_riscv32_virt.dtsi b/dts/riscv/renode_riscv32_virt.dtsi new file mode 100644 index 000000000000000..a0db375501f7c34 --- /dev/null +++ b/dts/riscv/renode_riscv32_virt.dtsi @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + clock-frequency = <0>; + compatible = "renode,virt", "riscv"; + device_type = "cpu"; + reg = <0>; + riscv,isa = "rv32imac_zicsr_zifencei"; + hlic: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "renode,virt-soc", "simple-bus"; + ranges; + + flash0: flash@80000000 { + compatible = "soc-nv-flash"; + reg = <0x80000000 DT_SIZE_M(4)>; + }; + + sram0: memory@80400000 { + compatible = "mmio-sram"; + reg = <0x80400000 DT_SIZE_M(4)>; + }; + + clint: clint@2000000 { + compatible = "sifive,clint0"; + interrupts-extended = <&hlic 3>, <&hlic 7>; + reg = <0x2000000 0x10000>; + }; + + plic0: interrupt-controller@c000000 { + compatible = "sifive,plic-1.0.0"; + #address-cells = <0>; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&hlic 11>; + reg = <0xc000000 0x04000000>; + riscv,max-priority = <1>; + riscv,ndev = <1023>; + }; + + plic1: interrupt-controller@8000000 { + compatible = "sifive,plic-1.0.0"; + #address-cells = <0>; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&hlic 4>; + reg = <0x8000000 0x04000000>; + riscv,max-priority = <1>; + riscv,ndev = <1023>; + }; + + uart0: uart@10000000 { + interrupts = < 0x0a 1 >; + interrupt-parent = < &plic0 >; + clock-frequency = <150000000>; + current-speed = <115200>; + reg = < 0x10000000 0x100 >; + compatible = "ns16550"; + reg-shift = < 0 >; + status = "disabled"; + }; + + uart1: uart@10000100 { + interrupts = < 0x0a 1 >; + interrupt-parent = < &plic1 >; + clock-frequency = <150000000>; + current-speed = <115200>; + reg = < 0x10000100 0x100 >; + compatible = "ns16550"; + reg-shift = < 0 >; + status = "disabled"; + }; + }; +}; diff --git a/include/zephyr/arch/riscv/arch.h b/include/zephyr/arch/riscv/arch.h index 1d173102de74085..1b456a48d965dcb 100644 --- a/include/zephyr/arch/riscv/arch.h +++ b/include/zephyr/arch/riscv/arch.h @@ -300,7 +300,7 @@ static inline uint64_t arch_k_cycle_get_64(void) #endif /*_ASMLANGUAGE */ -#if defined(CONFIG_SOC_FAMILY_RISCV_PRIVILEGED) +#if defined(CONFIG_RISCV_PRIVILEGED) #include #endif diff --git a/include/zephyr/bluetooth/audio/gmap_lc3_preset.h b/include/zephyr/bluetooth/audio/gmap_lc3_preset.h index 695df5dd79eef19..71289da22922285 100644 --- a/include/zephyr/bluetooth/audio/gmap_lc3_preset.h +++ b/include/zephyr/bluetooth/audio/gmap_lc3_preset.h @@ -17,7 +17,7 @@ * @brief Helper to declare LC3 32_1_gr codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_32_1_GR(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ @@ -27,7 +27,7 @@ * @brief Helper to declare LC3 32_2_gr codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_32_2_GR(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ @@ -37,7 +37,7 @@ * @brief Helper to declare LC3 48_1_gr codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_1_GR(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ @@ -49,7 +49,7 @@ * Mandatory to support as both unicast client and server * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_2_GR(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ @@ -59,7 +59,7 @@ * @brief Helper to declare LC3 48_3_gr codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_3_GR(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ @@ -71,7 +71,7 @@ * Mandatory to support as unicast server * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_4_GR(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ @@ -81,7 +81,7 @@ * @brief Helper to declare LC3 16_1_gs codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_16_1_GS(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ @@ -91,7 +91,7 @@ * @brief Helper to declare LC3 16_2_gs codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_16_2_GS(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ @@ -101,7 +101,7 @@ * @brief Helper to declare LC3 32_1_gs codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_32_1_GS(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ @@ -111,7 +111,7 @@ * @brief Helper to declare LC3 32_2_gs codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_32_2_GS(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ @@ -121,7 +121,7 @@ * @brief Helper to declare LC3 48_1_gs codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_1_GS(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ @@ -131,7 +131,7 @@ * @brief Helper to declare LC3 48_2_gs codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_2_GS(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ @@ -143,7 +143,7 @@ * @brief Helper to declare LC3 48_1_g codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_1_G(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ @@ -153,7 +153,7 @@ * @brief Helper to declare LC3 48_2_g codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_2_G(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ @@ -163,7 +163,7 @@ * @brief Helper to declare LC3 48_3_g codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_3_G(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ @@ -173,7 +173,7 @@ * @brief Helper to declare LC3 48_4_g codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) - * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) + * @param _stream_context Stream context (``BT_AUDIO_CONTEXT_*``) */ #define BT_GMAP_LC3_PRESET_48_4_G(_loc, _stream_context) \ BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ diff --git a/include/zephyr/bluetooth/audio/pbp.h b/include/zephyr/bluetooth/audio/pbp.h new file mode 100644 index 000000000000000..2ea85564fa7ca3d --- /dev/null +++ b/include/zephyr/bluetooth/audio/pbp.h @@ -0,0 +1,80 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_PBP_ +#define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_PBP_ + +/** + * @brief Public Broadcast Profile (PBP) + * + * @defgroup bt_pbp Public Broadcast Profile (PBP) + * + * @ingroup bluetooth + * @{ + * + * [Experimental] Users should note that the APIs can change + * as a part of ongoing development. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* PBA Service UUID + Public Broadcast Announcement features + Metadata Length */ +#define BT_PBP_MIN_PBA_SIZE (BT_UUID_SIZE_16 + 1 + 1) + +/** Public Broadcast Announcement features */ +enum bt_pbp_announcement_feature { + /** Broadcast Streams encryption status */ + BT_PBP_ANNOUNCEMENT_FEATURE_ENCRYPTION = BIT(0), + /** Standard Quality Public Broadcast Audio configuration */ + BT_PBP_ANNOUNCEMENT_FEATURE_STANDARD_QUALITY = BIT(1), + /** High Quality Public Broadcast Audio configuration */ + BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY = BIT(2), +}; + +/** + * @brief Creates a Public Broadcast Announcement based on the information received + * in the features parameter. + * + * @param meta Metadata to be included in the advertising data + * @param meta_len Size of the metadata fields to be included in the advertising data + * @param features Public Broadcast Announcement features + * @param pba_data_buf Pointer to store the PBA advertising data. Buffer size needs to be + * meta_len + @ref BT_PBP_MIN_PBA_SIZE. + * + * @return 0 on success or an appropriate error code. + */ +int bt_pbp_get_announcement(const uint8_t meta[], size_t meta_len, + enum bt_pbp_announcement_feature features, + struct net_buf_simple *pba_data_buf); + +/** + * @brief Parses the received advertising data corresponding to a Public Broadcast + * Announcement. Returns the advertised Public Broadcast Announcement features and metadata. + * + * @param data Advertising data to be checked + * @param features Public broadcast source features + * @param meta Pointer to copy the metadata present in the advertising data + * + * @return parsed metadata length on success or an appropriate error code + */ +uint8_t bt_pbp_parse_announcement(struct bt_data *data, + enum bt_pbp_announcement_feature *features, + uint8_t *meta); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_PBP_ */ diff --git a/include/zephyr/bluetooth/l2cap.h b/include/zephyr/bluetooth/l2cap.h index d9241e7af219353..3386c38bdb3a619 100644 --- a/include/zephyr/bluetooth/l2cap.h +++ b/include/zephyr/bluetooth/l2cap.h @@ -120,7 +120,7 @@ typedef enum bt_l2cap_chan_state { /** @brief Status of L2CAP channel. */ typedef enum bt_l2cap_chan_status { - /** Channel output status */ + /** Channel can send at least one PDU */ BT_L2CAP_STATUS_OUT, /** @brief Channel shutdown status diff --git a/include/zephyr/bluetooth/services/hrs.h b/include/zephyr/bluetooth/services/hrs.h index 097998f5caf3940..f19b2924ce07a1a 100644 --- a/include/zephyr/bluetooth/services/hrs.h +++ b/include/zephyr/bluetooth/services/hrs.h @@ -19,10 +19,50 @@ #include +#include + #ifdef __cplusplus extern "C" { #endif +/** @brief Heart rate service callback structure */ +struct bt_hrs_cb { + /** @brief Heart rate notifications changed + * + * @param enabled Flag that is true if notifications were enabled, false + * if they were disabled. + */ + void (*ntf_changed)(bool enabled); + + /** Internal member to form a list of callbacks */ + sys_snode_t _node; +}; + +/** @brief Heart rate service callback register + * + * This function will register callbacks that will be called in + * certain events related to Heart rate service. + * + * @param cb Pointer to callbacks structure. Must point to memory that remains valid + * until unregistered. + * + * @return 0 on success + * @return -EINVAL in case @p cb is NULL + */ +int bt_hrs_cb_register(struct bt_hrs_cb *cb); + +/** @brief Heart rate service callback unregister + * + * This function will unregister callback from Heart rate service. + * + * @param cb Pointer to callbacks structure + * + * @return 0 on success + * @return -EINVAL in case @p cb is NULL + * @return -ENOENT in case the @p cb was not found in registered callbacks + */ +int bt_hrs_cb_unregister(struct bt_hrs_cb *cb); + /** @brief Notify heart rate measurement. * * This will send a GATT notification to all current subscribers. diff --git a/include/zephyr/drivers/charger.h b/include/zephyr/drivers/charger.h index ec40b299d10799c..cf55fd88402d91f 100644 --- a/include/zephyr/drivers/charger.h +++ b/include/zephyr/drivers/charger.h @@ -56,6 +56,27 @@ enum charger_property { CHARGER_PROP_CHARGE_TERM_CURRENT_UA, /** Configuration of charge voltage regulation target in µV */ CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV, + /** + * Configuration of the input current regulation target in µA + * + * This value is a rising current threshold that is regulated by reducing the charge + * current output + */ + CHARGER_PROP_INPUT_REGULATION_CURRENT_UA, + /** + * Configuration of the input voltage regulation target in µV + * + * This value is a falling voltage threshold that is regulated by reducing the charge + * current output + */ + CHARGER_PROP_INPUT_REGULATION_VOLTAGE_UV, + /** + * Configuration to issue a notification to the system based on the input current + * level and timing + * + * Value should be of type struct charger_input_current_notifier + */ + CHARGER_PROP_INPUT_CURRENT_NOTIFICATION, /** Reserved to demark end of common charger properties */ CHARGER_PROP_COMMON_COUNT, /** @@ -173,6 +194,30 @@ enum charger_health { CHARGER_HEALTH_NO_BATTERY, }; +/** + * @brief Charger severity levels for system notifications + */ +enum charger_notification_severity { + /** Most severe level, typically triggered instantaneously */ + CHARGER_SEVERITY_PEAK = 0, + /** More severe than the warning level, less severe than peak */ + CHARGER_SEVERITY_CRITICAL, + /** Base severity level */ + CHARGER_SEVERITY_WARNING, +}; + +/** + * @brief The input current thresholds for the charger to notify the system + */ +struct charger_current_notifier { + /** The severity of the notification where CHARGER_SEVERITY_PEAK is the most severe */ + uint8_t severity; + /** The current threshold to be exceeded */ + uint32_t current_ua; + /** The duration of excess current before notifying the system */ + uint32_t duration_us; +}; + /** * @brief container for a charger_property value * @@ -200,6 +245,12 @@ union charger_propval { uint32_t charge_term_current_ua; /** CHARGER_PROP_CONSTANT_CHARGE_VOLTAGE_UV */ uint32_t const_charge_voltage_uv; + /** CHARGER_PROP_INPUT_REGULATION_CURRENT_UA */ + uint32_t input_current_regulation_current_ua; + /** CHARGER_PROP_INPUT_REGULATION_VOLTAGE_UV */ + uint32_t input_voltage_regulation_voltage_uv; + /** CHARGER_PROP_INPUT_CURRENT_NOTIFICATION */ + struct charger_current_notifier input_current_notification; }; /** diff --git a/include/zephyr/drivers/regulator.h b/include/zephyr/drivers/regulator.h index bad9de28239fd0e..7cf905f774e7fe9 100644 --- a/include/zephyr/drivers/regulator.h +++ b/include/zephyr/drivers/regulator.h @@ -140,6 +140,8 @@ struct regulator_common_config { int32_t min_ua; /** Maximum allowed current, in microamps. */ int32_t max_ua; + /** Initial current, in microamps. */ + int32_t init_ua; /** Startup delay, in microseconds. */ uint32_t startup_delay_us; /** Off to on delay, in microseconds. */ @@ -171,6 +173,8 @@ struct regulator_common_config { INT32_MIN), \ .max_ua = DT_PROP_OR(node_id, regulator_max_microamp, \ INT32_MAX), \ + .init_ua = DT_PROP_OR(node_id, regulator_init_microamp, \ + INT32_MIN), \ .startup_delay_us = DT_PROP_OR(node_id, startup_delay_us, 0), \ .off_on_delay_us = DT_PROP_OR(node_id, off_on_delay_us, 0), \ .allowed_modes = (const regulator_mode_t []) \ diff --git a/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h b/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h index fc7be3628d8fa15..fe011525846400d 100644 --- a/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h +++ b/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h @@ -42,6 +42,8 @@ #define IMX_CCM_LPI2C4_CLK 0x403UL #define IMX_CCM_LPI2C5_CLK 0x404UL #define IMX_CCM_LPI2C6_CLK 0x405UL +#define IMX_CCM_LPI2C7_CLK 0x406UL +#define IMX_CCM_LPI2C8_CLK 0x407UL /* LPSPI */ #define IMX_CCM_LPSPI_CLK 0x500UL @@ -51,6 +53,8 @@ #define IMX_CCM_LPSPI4_CLK 0x503UL #define IMX_CCM_LPSPI5_CLK 0x504UL #define IMX_CCM_LPSPI6_CLK 0x505UL +#define IMX_CCM_LPSPI7_CLK 0x506UL +#define IMX_CCM_LPSPI8_CLK 0x507UL /* USDHC */ #define IMX_CCM_USDHC1_CLK 0x600UL diff --git a/include/zephyr/input/input_analog_axis.h b/include/zephyr/input/input_analog_axis.h new file mode 100644 index 000000000000000..14492156d9c75bd --- /dev/null +++ b/include/zephyr/input/input_analog_axis.h @@ -0,0 +1,97 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_INPUT_ANALOG_AXIS_H_ +#define ZEPHYR_INCLUDE_INPUT_ANALOG_AXIS_H_ + +#include +#include + +/** + * @brief Analog axis API + * @defgroup input_analog_axis Analog axis API + * @ingroup io_interfaces + * @{ + */ + +/** + * @brief Analog axis calibration data structure. + * + * Holds the calibration data for a single analog axis. Initial values are set + * from the devicetree and can be changed by the applicatoin in runtime using + * @ref analog_axis_calibration_set and @ref analog_axis_calibration_get. + */ +struct analog_axis_calibration { + /** Input value that corresponds to the minimum output value. */ + int16_t in_min; + /** Input value that corresponds to the maximum output value. */ + int16_t in_max; + /** Output value deadzone relative to the output range. */ + uint16_t out_deadzone; +}; + +/** + * @brief Analog axis raw data callback. + * + * @param dev Analog axis device. + * @param channel Channel number. + * @param raw_val Raw value for the channel. + */ +typedef void (*analog_axis_raw_data_t)(const struct device *dev, + int channel, int16_t raw_val); + +/** + * @brief Set a raw data callback. + * + * Set a callback to receive raw data for the specified analog axis device. + * This is meant to be use in the application to acquire the data to use for + * calibration. Set cb to NULL to disable the callback. + * + * @param dev Analog axis device. + * @param cb An analog_axis_raw_data_t callback to use, NULL disable. + */ +void analog_axis_set_raw_data_cb(const struct device *dev, analog_axis_raw_data_t cb); + +/** + * @brief Get the number of defined axes. + * + * @retval n The number of defined axes for dev. + */ +int analog_axis_num_axes(const struct device *dev); + +/** + * @brief Get the axis calibration data. + * + * @param dev Analog axis device. + * @param channel Channel number. + * @param cal Pointer to an analog_axis_calibration structure that is going to + * get set with the current calibration data. + * + * @retval 0 If successful. + * @retval -EINVAL If the specified channel is not valid. + */ +int analog_axis_calibration_get(const struct device *dev, + int channel, + struct analog_axis_calibration *cal); + +/** + * @brief Set the axis calibration data. + * + * @param dev Analog axis device. + * @param channel Channel number. + * @param cal Pointer to an analog_axis_calibration structure with the new + * calibration data + * + * @retval 0 If successful. + * @retval -EINVAL If the specified channel is not valid. + */ +int analog_axis_calibration_set(const struct device *dev, + int channel, + struct analog_axis_calibration *cal); + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_INPUT_ANALOG_AXIS_H_ */ diff --git a/include/zephyr/input/input_analog_axis_settings.h b/include/zephyr/input/input_analog_axis_settings.h new file mode 100644 index 000000000000000..da8ad0ddfa3ae5c --- /dev/null +++ b/include/zephyr/input/input_analog_axis_settings.h @@ -0,0 +1,33 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_INPUT_ANALOG_AXIS_SETTINGS_H_ +#define ZEPHYR_INCLUDE_INPUT_ANALOG_AXIS_SETTINGS_H_ + +#include +#include + +/** + * @addtogroup input_analog_axis + * @{ + */ + +/** + * @brief Save the calibration data. + * + * Save the calibration data permanently on the specifided device, requires the + * the @ref settings subsystem to be configured and initialized. + * + * @param dev Analog axis device. + * + * @retval 0 If successful. + * @retval -errno In case of any other error. + */ +int analog_axis_calibration_save(const struct device *dev); + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_INPUT_ANALOG_AXIS_SETTINGS_H_ */ diff --git a/include/zephyr/llext/elf.h b/include/zephyr/llext/elf.h index 6dc3cc4e5c8e607..a9fd8f86a94c4c2 100644 --- a/include/zephyr/llext/elf.h +++ b/include/zephyr/llext/elf.h @@ -231,16 +231,16 @@ struct elf32_sym { struct elf64_sym { /** Name of the symbol as an index into the symbol string table */ elf64_word st_name; - /** Value or location of the symbol */ - elf64_addr st_value; - /** Size of the symbol */ - elf64_xword st_size; /** Symbol binding and type information */ unsigned char st_info; /** Symbol visibility */ unsigned char st_other; /** Symbols related section given by section header index */ elf64_half st_shndx; + /** Value or location of the symbol */ + elf64_addr st_value; + /** Size of the symbol */ + elf64_xword st_size; }; #define SHN_UNDEF 0 diff --git a/include/zephyr/llext/symbol.h b/include/zephyr/llext/symbol.h index 2c6505ee12f83ef..19f34649026b358 100644 --- a/include/zephyr/llext/symbol.h +++ b/include/zephyr/llext/symbol.h @@ -8,6 +8,7 @@ #define ZEPHYR_LLEXT_SYMBOL_H #include +#include #include #ifdef __cplusplus @@ -78,8 +79,9 @@ struct llext_symtable { .name = STRINGIFY(x), .addr = &x, \ } -#define LL_EXTENSION_SYMBOL(x) struct llext_symbol __attribute__((section(".exported_sym"), used)) \ - symbol_##x = {STRINGIFY(x), &x} +#define LL_EXTENSION_SYMBOL(x) \ + struct llext_symbol Z_GENERIC_SECTION(".exported_sym") __used \ + symbol_##x = {STRINGIFY(x), &x} /** * @brief Export a system call to a table of symbols diff --git a/include/zephyr/net/ieee802154_pkt.h b/include/zephyr/net/ieee802154_pkt.h index d5fdc712b499f48..3270f9942483df0 100644 --- a/include/zephyr/net/ieee802154_pkt.h +++ b/include/zephyr/net/ieee802154_pkt.h @@ -59,12 +59,6 @@ struct net_pkt_cb_ieee802154 { */ uint8_t rssi; }; -#if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER) - /* TX packets */ - struct { - int8_t txpwr; /* TX power in dBm. */ - }; -#endif /* CONFIG_IEEE802154_SELECTIVE_TXPOWER */ }; /* Flags */ @@ -185,18 +179,6 @@ static inline void net_pkt_set_ieee802154_rssi_dbm(struct net_pkt *pkt, int16_t CODE_UNREACHABLE; } -#if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER) -static inline int8_t net_pkt_ieee802154_txpwr(struct net_pkt *pkt) -{ - return net_pkt_cb_ieee802154(pkt)->txpwr; -} - -static inline void net_pkt_set_ieee802154_txpwr(struct net_pkt *pkt, int8_t txpwr) -{ - net_pkt_cb_ieee802154(pkt)->txpwr = txpwr; -} -#endif /* CONFIG_IEEE802154_SELECTIVE_TXPOWER */ - static inline bool net_pkt_ieee802154_ack_fpb(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->ack_fpb; diff --git a/include/zephyr/posix/posix_types.h b/include/zephyr/posix/posix_types.h index 175943950b7ca20..3420d562679bfa7 100644 --- a/include/zephyr/posix/posix_types.h +++ b/include/zephyr/posix/posix_types.h @@ -21,6 +21,8 @@ extern "C" { #endif +typedef int pid_t; + #ifndef __useconds_t_defined typedef unsigned long useconds_t; #endif diff --git a/include/zephyr/posix/semaphore.h b/include/zephyr/posix/semaphore.h index 943218ee08e82a6..3b0f53b07123c0a 100644 --- a/include/zephyr/posix/semaphore.h +++ b/include/zephyr/posix/semaphore.h @@ -13,6 +13,8 @@ extern "C" { #endif +#define SEM_FAILED ((sem_t *) 0) + int sem_destroy(sem_t *semaphore); int sem_getvalue(sem_t *ZRESTRICT semaphore, int *ZRESTRICT value); int sem_init(sem_t *semaphore, int pshared, unsigned int value); @@ -20,6 +22,9 @@ int sem_post(sem_t *semaphore); int sem_timedwait(sem_t *ZRESTRICT semaphore, struct timespec *ZRESTRICT abstime); int sem_trywait(sem_t *semaphore); int sem_wait(sem_t *semaphore); +sem_t *sem_open(const char *name, int oflags, ...); +int sem_unlink(const char *name); +int sem_close(sem_t *sem); #ifdef __cplusplus } diff --git a/include/zephyr/posix/time.h b/include/zephyr/posix/time.h index ea7e68cb079e97a..417923c4377b042 100644 --- a/include/zephyr/posix/time.h +++ b/include/zephyr/posix/time.h @@ -69,6 +69,10 @@ extern "C" { #define CLOCK_REALTIME 1 #endif +#ifndef CLOCK_PROCESS_CPUTIME_ID +#define CLOCK_PROCESS_CPUTIME_ID 2 +#endif + #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC 4 #endif @@ -84,6 +88,7 @@ static inline int32_t _ts_to_ms(const struct timespec *to) int clock_gettime(clockid_t clock_id, struct timespec *ts); int clock_settime(clockid_t clock_id, const struct timespec *ts); +int clock_getcpuclockid(pid_t pid, clockid_t *clock_id); /* Timer APIs */ int timer_create(clockid_t clockId, struct sigevent *evp, timer_t *timerid); int timer_delete(timer_t timerid); diff --git a/include/zephyr/posix/unistd.h b/include/zephyr/posix/unistd.h index b55cf702fec2641..84faf7c1c8f28d4 100644 --- a/include/zephyr/posix/unistd.h +++ b/include/zephyr/posix/unistd.h @@ -51,6 +51,7 @@ extern char *optarg; extern int opterr, optind, optopt; #endif +pid_t getpid(void); unsigned sleep(unsigned int seconds); int usleep(useconds_t useconds); diff --git a/include/zephyr/sys/arch_interface.h b/include/zephyr/sys/arch_interface.h index d044f578fae4f76..dd5755c1e231fbc 100644 --- a/include/zephyr/sys/arch_interface.h +++ b/include/zephyr/sys/arch_interface.h @@ -495,6 +495,9 @@ static inline uint32_t arch_proc_id(void); */ void arch_sched_ipi(void); + +int arch_smp_init(void); + #endif /* CONFIG_SMP */ /** diff --git a/include/zephyr/sys/byteorder.h b/include/zephyr/sys/byteorder.h index 978255fd02dab56..d1f839f5188309f 100644 --- a/include/zephyr/sys/byteorder.h +++ b/include/zephyr/sys/byteorder.h @@ -16,22 +16,21 @@ #include #include -/* Internal helpers only used by the sys_* APIs further below */ -#define __bswap_16(x) ((uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))) -#define __bswap_24(x) ((uint32_t) ((((x) >> 16) & 0xff) | \ +#define BSWAP_16(x) ((uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))) +#define BSWAP_24(x) ((uint32_t) ((((x) >> 16) & 0xff) | \ (((x)) & 0xff00) | \ (((x) & 0xff) << 16))) -#define __bswap_32(x) ((uint32_t) ((((x) >> 24) & 0xff) | \ +#define BSWAP_32(x) ((uint32_t) ((((x) >> 24) & 0xff) | \ (((x) >> 8) & 0xff00) | \ (((x) & 0xff00) << 8) | \ (((x) & 0xff) << 24))) -#define __bswap_48(x) ((uint64_t) ((((x) >> 40) & 0xff) | \ +#define BSWAP_48(x) ((uint64_t) ((((x) >> 40) & 0xff) | \ (((x) >> 24) & 0xff00) | \ (((x) >> 8) & 0xff0000) | \ (((x) & 0xff0000) << 8) | \ (((x) & 0xff00) << 24) | \ (((x) & 0xff) << 40))) -#define __bswap_64(x) ((uint64_t) ((((x) >> 56) & 0xff) | \ +#define BSWAP_64(x) ((uint64_t) ((((x) >> 56) & 0xff) | \ (((x) >> 40) & 0xff00) | \ (((x) >> 24) & 0xff0000) | \ (((x) >> 8) & 0xff000000) | \ @@ -222,16 +221,16 @@ #define sys_cpu_to_le48(val) (val) #define sys_le64_to_cpu(val) (val) #define sys_cpu_to_le64(val) (val) -#define sys_be16_to_cpu(val) __bswap_16(val) -#define sys_cpu_to_be16(val) __bswap_16(val) -#define sys_be24_to_cpu(val) __bswap_24(val) -#define sys_cpu_to_be24(val) __bswap_24(val) -#define sys_be32_to_cpu(val) __bswap_32(val) -#define sys_cpu_to_be32(val) __bswap_32(val) -#define sys_be48_to_cpu(val) __bswap_48(val) -#define sys_cpu_to_be48(val) __bswap_48(val) -#define sys_be64_to_cpu(val) __bswap_64(val) -#define sys_cpu_to_be64(val) __bswap_64(val) +#define sys_be16_to_cpu(val) BSWAP_16(val) +#define sys_cpu_to_be16(val) BSWAP_16(val) +#define sys_be24_to_cpu(val) BSWAP_24(val) +#define sys_cpu_to_be24(val) BSWAP_24(val) +#define sys_be32_to_cpu(val) BSWAP_32(val) +#define sys_cpu_to_be32(val) BSWAP_32(val) +#define sys_be48_to_cpu(val) BSWAP_48(val) +#define sys_cpu_to_be48(val) BSWAP_48(val) +#define sys_be64_to_cpu(val) BSWAP_64(val) +#define sys_cpu_to_be64(val) BSWAP_64(val) #define sys_uint16_to_array(val) { \ ((val) & 0xff), \ @@ -254,16 +253,16 @@ (((val) >> 56) & 0xff)} #else -#define sys_le16_to_cpu(val) __bswap_16(val) -#define sys_cpu_to_le16(val) __bswap_16(val) -#define sys_le24_to_cpu(val) __bswap_24(val) -#define sys_cpu_to_le24(val) __bswap_24(val) -#define sys_le32_to_cpu(val) __bswap_32(val) -#define sys_cpu_to_le32(val) __bswap_32(val) -#define sys_le48_to_cpu(val) __bswap_48(val) -#define sys_cpu_to_le48(val) __bswap_48(val) -#define sys_le64_to_cpu(val) __bswap_64(val) -#define sys_cpu_to_le64(val) __bswap_64(val) +#define sys_le16_to_cpu(val) BSWAP_16(val) +#define sys_cpu_to_le16(val) BSWAP_16(val) +#define sys_le24_to_cpu(val) BSWAP_24(val) +#define sys_cpu_to_le24(val) BSWAP_24(val) +#define sys_le32_to_cpu(val) BSWAP_32(val) +#define sys_cpu_to_le32(val) BSWAP_32(val) +#define sys_le48_to_cpu(val) BSWAP_48(val) +#define sys_cpu_to_le48(val) BSWAP_48(val) +#define sys_le64_to_cpu(val) BSWAP_64(val) +#define sys_cpu_to_le64(val) BSWAP_64(val) #define sys_be16_to_cpu(val) (val) #define sys_cpu_to_be16(val) (val) #define sys_be24_to_cpu(val) (val) diff --git a/include/zephyr/sys/util.h b/include/zephyr/sys/util.h index 45ae20089996728..97bfd3aa714841d 100644 --- a/include/zephyr/sys/util.h +++ b/include/zephyr/sys/util.h @@ -657,6 +657,45 @@ char *utf8_lcpy(char *dst, const char *src, size_t n); (((buflen) != 0) && \ ((UINTPTR_MAX - (uintptr_t)(addr)) <= ((uintptr_t)((buflen) - 1)))) +/** + * @brief XOR n bytes + * + * @param dst Destination of where to store result. Shall be @p len bytes. + * @param src1 First source. Shall be @p len bytes. + * @param src2 Second source. Shall be @p len bytes. + * @param len Number of bytes to XOR. + */ +static inline void mem_xor_n(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, size_t len) +{ + while (len--) { + *dst++ = *src1++ ^ *src2++; + } +} + +/** + * @brief XOR 32 bits + * + * @param dst Destination of where to store result. Shall be 32 bits. + * @param src1 First source. Shall be 32 bits. + * @param src2 Second source. Shall be 32 bits. + */ +static inline void mem_xor_32(uint8_t dst[4], const uint8_t src1[4], const uint8_t src2[4]) +{ + mem_xor_n(dst, src1, src2, 4U); +} + +/** + * @brief XOR 128 bits + * + * @param dst Destination of where to store result. Shall be 128 bits. + * @param src1 First source. Shall be 128 bits. + * @param src2 Second source. Shall be 128 bits. + */ +static inline void mem_xor_128(uint8_t dst[16], const uint8_t src1[16], const uint8_t src2[16]) +{ + mem_xor_n(dst, src1, src2, 16); +} + #ifdef __cplusplus } #endif diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 716ee9821f4afdb..28d27f10723f107 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -703,16 +703,16 @@ int usbd_device_set_pid(struct usbd_contex *const uds_ctx, /** * @brief Set USB device descriptor code triple Base Class, SubClass, and Protocol * - * @param[in] uds_ctx Pointer to USB device support context - * @param[in] class bDeviceClass value - * @param[in] subclass bDeviceSubClass value - * @param[in] protocol bDeviceProtocol value + * @param[in] uds_ctx Pointer to USB device support context + * @param[in] base_class bDeviceClass value + * @param[in] subclass bDeviceSubClass value + * @param[in] protocol bDeviceProtocol value * * @return 0 on success, other values on fail. */ int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx, - const uint8_t class, const uint8_t subclass, - const uint8_t protocol); + const uint8_t base_class, + const uint8_t subclass, const uint8_t protocol); /** * @brief Setup USB device configuration attribute Remote Wakeup diff --git a/kernel/sched.c b/kernel/sched.c index 2e15b6659600d5e..bb009238d5db674 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1527,26 +1527,28 @@ static inline void z_vrfy_k_yield(void) static int32_t z_tick_sleep(k_ticks_t ticks) { -#ifdef CONFIG_MULTITHREADING uint32_t expected_wakeup_ticks; __ASSERT(!arch_is_in_isr(), ""); LOG_DBG("thread %p for %lu ticks", _current, (unsigned long)ticks); +#ifdef CONFIG_MULTITHREADING /* wait of 0 ms is treated as a 'yield' */ if (ticks == 0) { k_yield(); return 0; } +#endif - k_timeout_t timeout = Z_TIMEOUT_TICKS(ticks); if (Z_TICK_ABS(ticks) <= 0) { expected_wakeup_ticks = ticks + sys_clock_tick_get_32(); } else { expected_wakeup_ticks = Z_TICK_ABS(ticks); } +#ifdef CONFIG_MULTITHREADING + k_timeout_t timeout = Z_TIMEOUT_TICKS(ticks); k_spinlock_key_t key = k_spin_lock(&sched_spinlock); #if defined(CONFIG_TIMESLICING) && defined(CONFIG_SWAP_NONATOMIC) @@ -1564,6 +1566,9 @@ static int32_t z_tick_sleep(k_ticks_t ticks) if (ticks > 0) { return ticks; } +#else + /* busy wait to be time coherent since subsystems may depend on it */ + z_impl_k_busy_wait(k_ticks_to_us_ceil32(expected_wakeup_ticks)); #endif return 0; @@ -1579,8 +1584,12 @@ int32_t z_impl_k_sleep(k_timeout_t timeout) /* in case of K_FOREVER, we suspend */ if (K_TIMEOUT_EQ(timeout, K_FOREVER)) { +#ifdef CONFIG_MULTITHREADING k_thread_suspend(_current); - +#else + /* In Single Thread, just wait for an interrupt saving power */ + k_cpu_idle(); +#endif SYS_PORT_TRACING_FUNC_EXIT(k_thread, sleep, timeout, (int32_t) K_TICKS_FOREVER); return (int32_t) K_TICKS_FOREVER; diff --git a/lib/posix/Kconfig.clock b/lib/posix/Kconfig.clock index 95c88769d739d8e..e9b83a12d0add8a 100644 --- a/lib/posix/Kconfig.clock +++ b/lib/posix/Kconfig.clock @@ -5,7 +5,7 @@ config POSIX_CLOCK bool "POSIX clock, timer, and sleep APIs" default y if POSIX_API - depends on !(ARCH_POSIX && EXTERNAL_LIBC) + depends on !NATIVE_LIBC help This enables POSIX clock\_\*(), timer\_\*(), and \*sleep() functions. diff --git a/lib/posix/Kconfig.semaphore b/lib/posix/Kconfig.semaphore index d9b9b47a5089f8f..aa3468fea763191 100644 --- a/lib/posix/Kconfig.semaphore +++ b/lib/posix/Kconfig.semaphore @@ -8,3 +8,11 @@ config SEM_VALUE_MAX range 1 32767 help Maximum semaphore count in POSIX compliant Application. + +config SEM_NAMELEN_MAX + int "Maximum name length" + default 16 + range 2 255 + help + Maximum length of name for a named semaphore. + The max value of 255 corresponds to {NAME_MAX}. diff --git a/lib/posix/clock.c b/lib/posix/clock.c index 0d085a6d0d00c9d..1a59aa741f90648 100644 --- a/lib/posix/clock.c +++ b/lib/posix/clock.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -222,3 +223,15 @@ int gettimeofday(struct timeval *tv, void *tz) return res; } + +int clock_getcpuclockid(pid_t pid, clockid_t *clock_id) +{ + /* We don't allow any process ID but our own. */ + if (pid != 0 && pid != getpid()) { + return EPERM; + } + + *clock_id = CLOCK_PROCESS_CPUTIME_ID; + + return 0; +} diff --git a/lib/posix/getopt/getopt.c b/lib/posix/getopt/getopt.c index 514af721cb525fb..c17a0ff04c238b7 100644 --- a/lib/posix/getopt/getopt.c +++ b/lib/posix/getopt/getopt.c @@ -30,7 +30,7 @@ */ #include -#ifdef CONFIG_ARCH_POSIX +#ifdef CONFIG_NATIVE_LIBC #include #else #include diff --git a/lib/posix/pthread.c b/lib/posix/pthread.c index 131242866a05bab..2e2c49f2a35bdb1 100644 --- a/lib/posix/pthread.c +++ b/lib/posix/pthread.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -158,6 +159,22 @@ int pthread_equal(pthread_t pt1, pthread_t pt2) return (pt1 == pt2); } +pid_t getpid(void) +{ + /* + * To maintain compatibility with some other POSIX operating systems, + * a PID of zero is used to indicate that the process exists in another namespace. + * PID zero is also used by the scheduler in some cases. + * PID one is usually reserved for the init process. + * Also note, that negative PIDs may be used by kill() + * to send signals to process groups in some implementations. + * + * At the moment, getpid just returns an arbitrary number >= 2 + */ + + return 42; +} + static inline void __z_pthread_cleanup_init(struct __pthread_cleanup *c, void (*routine)(void *arg), void *arg) { diff --git a/lib/posix/semaphore.c b/lib/posix/semaphore.c index 7a1392cd5211383..07ec11add4e599a 100644 --- a/lib/posix/semaphore.c +++ b/lib/posix/semaphore.c @@ -1,11 +1,78 @@ /* * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Meta * * SPDX-License-Identifier: Apache-2.0 */ #include +#include +#include +#include #include +#include + +struct nsem_obj { + sys_snode_t snode; + sem_t sem; + int ref_count; + char *name; +}; + +/* Initialize the list */ +static sys_slist_t nsem_list = SYS_SLIST_STATIC_INIT(&nsem_list); + +static K_MUTEX_DEFINE(nsem_mutex); + +static inline void nsem_list_lock(void) +{ + k_mutex_lock(&nsem_mutex, K_FOREVER); +} + +static inline void nsem_list_unlock(void) +{ + k_mutex_unlock(&nsem_mutex); +} + +static struct nsem_obj *nsem_find(const char *name) +{ + struct nsem_obj *nsem; + + SYS_SLIST_FOR_EACH_CONTAINER(&nsem_list, nsem, snode) { + if ((nsem->name != NULL) && (strcmp(nsem->name, name) == 0)) { + return nsem; + } + } + + return NULL; +} + +/* Clean up a named semaphore object completely (incl its `name` buffer) */ +static void nsem_cleanup(struct nsem_obj *nsem) +{ + if (nsem != NULL) { + if (nsem->name != NULL) { + k_free(nsem->name); + } + k_free(nsem); + } +} + +/* Remove a named semaphore if it isn't unsed */ +static void nsem_unref(struct nsem_obj *nsem) +{ + nsem->ref_count -= 1; + __ASSERT(nsem->ref_count >= 0, "ref_count may not be negative"); + + if (nsem->ref_count == 0) { + __ASSERT(nsem->name == NULL, "ref_count is 0 but sem is not unlinked"); + + sys_slist_find_and_remove(&nsem_list, (sys_snode_t *) nsem); + + /* Free nsem */ + nsem_cleanup(nsem); + } +} /** * @brief Destroy semaphore. @@ -148,3 +215,172 @@ int sem_wait(sem_t *semaphore) (void)k_sem_take(semaphore, K_FOREVER); return 0; } + +sem_t *sem_open(const char *name, int oflags, ...) +{ + va_list va; + mode_t mode; + unsigned int value; + struct nsem_obj *nsem = NULL; + size_t namelen; + + va_start(va, oflags); + BUILD_ASSERT(sizeof(mode_t) <= sizeof(int)); + mode = va_arg(va, int); + value = va_arg(va, unsigned int); + va_end(va); + + if (value > CONFIG_SEM_VALUE_MAX) { + errno = EINVAL; + return (sem_t *)SEM_FAILED; + } + + if (name == NULL) { + errno = EINVAL; + return (sem_t *)SEM_FAILED; + } + + namelen = strlen(name); + if ((namelen + 1) > CONFIG_SEM_NAMELEN_MAX) { + errno = ENAMETOOLONG; + return (sem_t *)SEM_FAILED; + } + + /* Lock before checking to make sure that the call is atomic */ + nsem_list_lock(); + + /* Check if the named semaphore exists */ + nsem = nsem_find(name); + + if (nsem != NULL) { /* Named semaphore exists */ + if (((oflags & O_CREAT) != 0) && ((oflags & O_EXCL) != 0)) { + errno = EEXIST; + goto error_unlock; + } + + __ASSERT_NO_MSG(nsem->ref_count != INT_MAX); + nsem->ref_count++; + goto unlock; + } + + /* Named sempahore doesn't exist, try to create new one */ + + if ((oflags & O_CREAT) == 0) { + errno = ENOENT; + goto error_unlock; + } + + nsem = k_calloc(1, sizeof(struct nsem_obj)); + if (nsem == NULL) { + errno = ENOSPC; + goto error_unlock; + } + + /* goto `cleanup_error_unlock` past this point to avoid memory leak */ + + nsem->name = k_calloc(namelen + 1, sizeof(uint8_t)); + if (nsem->name == NULL) { + errno = ENOSPC; + goto cleanup_error_unlock; + } + + strcpy(nsem->name, name); + + /* 1 for this open instance, +1 for the linked name */ + nsem->ref_count = 2; + + (void)k_sem_init(&nsem->sem, value, CONFIG_SEM_VALUE_MAX); + + sys_slist_append(&nsem_list, (sys_snode_t *)&(nsem->snode)); + + goto unlock; + +cleanup_error_unlock: + nsem_cleanup(nsem); + +error_unlock: + nsem = NULL; + +unlock: + nsem_list_unlock(); + return nsem == NULL ? SEM_FAILED : &nsem->sem; +} + +int sem_unlink(const char *name) +{ + int ret = 0; + struct nsem_obj *nsem; + + if (name == NULL) { + errno = EINVAL; + return -1; + } + + if ((strlen(name) + 1) > CONFIG_SEM_NAMELEN_MAX) { + errno = ENAMETOOLONG; + return -1; + } + + nsem_list_lock(); + + /* Check if queue already exists */ + nsem = nsem_find(name); + if (nsem == NULL) { + ret = -1; + errno = ENOENT; + goto unlock; + } + + k_free(nsem->name); + nsem->name = NULL; + nsem_unref(nsem); + +unlock: + nsem_list_unlock(); + return ret; +} + +int sem_close(sem_t *sem) +{ + struct nsem_obj *nsem = CONTAINER_OF(sem, struct nsem_obj, sem); + + if (sem == NULL) { + errno = EINVAL; + return -1; + } + + nsem_list_lock(); + nsem_unref(nsem); + nsem_list_unlock(); + return 0; +} + +#ifdef CONFIG_ZTEST +/* Used by ztest to get the ref count of a named semaphore */ +int nsem_get_ref_count(sem_t *sem) +{ + struct nsem_obj *nsem = CONTAINER_OF(sem, struct nsem_obj, sem); + int ref_count; + + __ASSERT_NO_MSG(sem != NULL); + __ASSERT_NO_MSG(nsem != NULL); + + nsem_list_lock(); + ref_count = nsem->ref_count; + nsem_list_unlock(); + + return ref_count; +} + +/* Used by ztest to get the length of the named semaphore */ +size_t nsem_get_list_len(void) +{ + size_t len; + + nsem_list_lock(); + len = sys_slist_len(&nsem_list); + nsem_list_unlock(); + + return len; +} +#endif diff --git a/modules/Kconfig.infineon b/modules/Kconfig.infineon index 4147d138de32c50..070508ccce4a735 100644 --- a/modules/Kconfig.infineon +++ b/modules/Kconfig.infineon @@ -55,4 +55,9 @@ config HAS_XMCLIB_WDT help Enable XMCLIB WDT +config HAS_XMCLIB_ETH + bool + help + Enable XMCLIB Ethernet MAC + endif # HAS_XMCLIB diff --git a/modules/hal_gigadevice/CMakeLists.txt b/modules/hal_gigadevice/CMakeLists.txt index 7a4096bc4d2f074..3b887f654a98854 100644 --- a/modules/hal_gigadevice/CMakeLists.txt +++ b/modules/hal_gigadevice/CMakeLists.txt @@ -6,9 +6,9 @@ if(CONFIG_HAS_GD32_HAL) string(TOUPPER ${CONFIG_SOC} gd32_soc_uc) set(gd32_soc_dir ${ZEPHYR_HAL_GIGADEVICE_MODULE_DIR}/${CONFIG_SOC_SERIES}) -if(CONFIG_SOC_FAMILY_GD32_ARM) +if(CONFIG_ARM) set(gd32_soc_sys_dir ${gd32_soc_dir}/cmsis/gd/${CONFIG_SOC_SERIES}) -elseif(CONFIG_SOC_SERIES_GD32VF103) +elseif(CONFIG_RISCV) set(gd32_soc_sys_dir ${gd32_soc_dir}/riscv) zephyr_include_directories(${gd32_soc_dir}/riscv/drivers) endif() diff --git a/modules/hal_gigadevice/Kconfig b/modules/hal_gigadevice/Kconfig index 66132779eb17597..84f6532b251a14f 100644 --- a/modules/hal_gigadevice/Kconfig +++ b/modules/hal_gigadevice/Kconfig @@ -16,7 +16,7 @@ config GD32_HAS_AFIO_PINMUX config HAS_GD32_HAL bool - select HAS_CMSIS_CORE if SOC_FAMILY_GD32_ARM + select HAS_CMSIS_CORE if ARM if HAS_GD32_HAL diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index c4bfcc2d60ee5c3..a92aa93d9a2f883 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -63,8 +63,37 @@ config NRFX_EGU5 select NRFX_EGU config NRFX_GPIOTE - bool "GPIOTE driver" - depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + bool + +config NRFX_GPIOTE0 + bool "GPIOTE0 driver instance" + depends on $(dt_nodelabel_has_compat,gpiote0,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + select NRFX_GPIOTE + +config NRFX_GPIOTE1 + bool "GPIOTE1 driver instance" + depends on $(dt_nodelabel_has_compat,gpiote1,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + select NRFX_GPIOTE + +config NRFX_GPIOTE20 + bool "NRFX_GPIOTE20 driver instance" + depends on $(dt_nodelabel_has_compat,gpiote20,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + select NRFX_GPIOTE + +config NRFX_GPIOTE30 + bool "NRFX_GPIOTE30 driver instance" + depends on $(dt_nodelabel_has_compat,gpiote30,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + select NRFX_GPIOTE + +config NRFX_GPIOTE130 + bool "NRFX_GPIOTE130 driver instance" + depends on $(dt_nodelabel_has_compat,gpiote130,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + select NRFX_GPIOTE + +config NRFX_GPIOTE131 + bool "NRFX_GPIOTE131 driver instance" + depends on $(dt_nodelabel_has_compat,gpiote131,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + select NRFX_GPIOTE config NRFX_GPIOTE_NUM_OF_EVT_HANDLERS int "Number of event handlers" diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index a285d1c86dbbee3..57417644c321ba7 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -9,12 +9,6 @@ #include -/* - * NRFX API version 2.10 flag. - * When the flag is set NRFX API is compatible with the newest NRFX release. - */ -#define NRFX_CONFIG_API_VER_2_10 1 - /* * These are mappings of Kconfig options enabling nrfx drivers and particular * peripheral instances to the corresponding symbols used inside of nrfx. @@ -117,15 +111,24 @@ #ifdef CONFIG_NRFX_GPIOTE #define NRFX_GPIOTE_ENABLED 1 -#if (defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_SERIES_NRF53X)) \ - && defined(NRF_TRUSTZONE_NONSECURE) -#define NRFX_GPIOTE1_ENABLED 1 -#else +#endif +#ifdef CONFIG_NRFX_GPIOTE0 #define NRFX_GPIOTE0_ENABLED 1 #endif +#ifdef CONFIG_NRFX_GPIOTE1 +#define NRFX_GPIOTE1_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_GPIOTE20 +#define NRFX_GPIOTE20_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_GPIOTE30 +#define NRFX_GPIOTE30_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_GPIOTE130 +#define NRFX_GPIOTE130_ENABLED 1 #endif -#ifdef CONFIG_NRFX_GPIOTE_LOG -#define NRFX_GPIOTE_CONFIG_LOG_ENABLED 1 +#ifdef CONFIG_NRFX_GPIOTE131 +#define NRFX_GPIOTE131_ENABLED 1 #endif #ifdef CONFIG_NRFX_GPIOTE_NUM_OF_EVT_HANDLERS diff --git a/modules/hal_nordic/nrfx/nrfx_config_common.h b/modules/hal_nordic/nrfx/nrfx_config_common.h index 8c0a58713a05ba5..28a3a15b0deff7b 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_common.h +++ b/modules/hal_nordic/nrfx/nrfx_config_common.h @@ -18,7 +18,7 @@ /** @brief Symbol specifying minor version of the nrfx API to be used. */ #ifndef NRFX_CONFIG_API_VER_MINOR -#define NRFX_CONFIG_API_VER_MINOR 0 +#define NRFX_CONFIG_API_VER_MINOR 2 #endif /** @brief Symbol specifying micro version of the nrfx API to be used. */ diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf5340_application.h b/modules/hal_nordic/nrfx/nrfx_config_nrf5340_application.h index 4a42f92ca98f531..18bcc40b2ac3afe 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf5340_application.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf5340_application.h @@ -83,6 +83,7 @@ * between secure and non-secure mapping. */ #if defined(NRF_TRUSTZONE_NONSECURE) +#define NRF_GPIOTE NRF_GPIOTE1 #define NRF_GPIOTE1 NRF_GPIOTE1_NS #else #define NRF_CACHE NRF_CACHE_S @@ -91,20 +92,14 @@ #define NRF_CRYPTOCELL NRF_CRYPTOCELL_S #define NRF_CTI NRF_CTI_S #define NRF_FICR NRF_FICR_S +#define NRF_GPIOTE NRF_GPIOTE0 #define NRF_GPIOTE0 NRF_GPIOTE0_S +#define NRF_GPIOTE1 NRF_GPIOTE1_NS #define NRF_SPU NRF_SPU_S #define NRF_TAD NRF_TAD_S #define NRF_UICR NRF_UICR_S #endif -/* Fixups for the GPIOTE driver. */ -#if defined(NRF_TRUSTZONE_NONSECURE) -#define NRF_GPIOTE NRF_GPIOTE1 -#else -#define NRF_GPIOTE NRF_GPIOTE0 -#endif - - /** * @brief NRFX_DEFAULT_IRQ_PRIORITY * diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf91.h b/modules/hal_nordic/nrfx/nrfx_config_nrf91.h index 873be583a35b883..c6029a186284151 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf91.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf91.h @@ -67,25 +67,21 @@ * between secure and non-secure mapping. */ #if defined(NRF_TRUSTZONE_NONSECURE) +#define NRF_GPIOTE NRF_GPIOTE1 #define NRF_GPIOTE1 NRF_GPIOTE1_NS #else #define NRF_CC_HOST_RGF NRF_CC_HOST_RGF_S #define NRF_CRYPTOCELL NRF_CRYPTOCELL_S #define NRF_CTRL_AP_PERI NRF_CTRL_AP_PERI_S #define NRF_FICR NRF_FICR_S +#define NRF_GPIOTE NRF_GPIOTE0 #define NRF_GPIOTE0 NRF_GPIOTE0_S +#define NRF_GPIOTE1 NRF_GPIOTE1_NS #define NRF_SPU NRF_SPU_S #define NRF_TAD NRF_TAD_S #define NRF_UICR NRF_UICR_S #endif -/* Fixups for the GPIOTE driver. */ -#if defined(NRF_TRUSTZONE_NONSECURE) -#define NRF_GPIOTE NRF_GPIOTE1 -#else -#define NRF_GPIOTE NRF_GPIOTE0 -#endif - /** * @brief NRFX_DEFAULT_IRQ_PRIORITY * diff --git a/modules/hal_nxp/usb/usb_device_config.h b/modules/hal_nxp/usb/usb_device_config.h index 31a62ffbfebc522..09af4fe7be62550 100644 --- a/modules/hal_nxp/usb/usb_device_config.h +++ b/modules/hal_nxp/usb/usb_device_config.h @@ -52,4 +52,9 @@ BUILD_ASSERT(NUM_INSTS <= 1, "Only one USB device supported"); /* Number of endpoints supported */ #define USB_DEVICE_CONFIG_ENDPOINTS (DT_INST_PROP(0, num_bidir_endpoints)) +/* Start of Frame (SOF) Notifications are required by the zephyr usb audio driver */ +#ifdef CONFIG_USB_DEVICE_AUDIO +#define USB_DEVICE_CONFIG_SOF_NOTIFICATIONS (1U) +#endif /* CONFIG_USB_DEVICE_AUDIO */ + #endif /* __USB_DEVICE_CONFIG_H__ */ diff --git a/modules/openthread/CMakeLists.txt b/modules/openthread/CMakeLists.txt index 6691084eebdeef6..c9ccf074649e576 100644 --- a/modules/openthread/CMakeLists.txt +++ b/modules/openthread/CMakeLists.txt @@ -15,6 +15,7 @@ endmacro() set(OT_BUILD_EXECUTABLES OFF CACHE BOOL "Disable OpenThread samples") set(OT_BUILTIN_MBEDTLS_MANAGEMENT OFF CACHE BOOL "Use Zephyr's mbedTLS heap") set(OT_PLATFORM "zephyr" CACHE STRING "Zephyr as a target platform") +set(OT_PLATFORM_POWER_CALIBRATION OFF CACHE BOOL "Use Zephyr's power calibration handled by Radio Driver") set(OT_THREAD_VERSION ${CONFIG_OPENTHREAD_THREAD_VERSION} CACHE STRING "User selected Thread stack version") set(OT_CLI_TRANSPORT "CONSOLE" CACHE STRING "Set CLI to use console interpreter") diff --git a/modules/openthread/platform/openthread-core-zephyr-config.h b/modules/openthread/platform/openthread-core-zephyr-config.h index 773cd170f2ccba4..71a087ca0b501a9 100644 --- a/modules/openthread/platform/openthread-core-zephyr-config.h +++ b/modules/openthread/platform/openthread-core-zephyr-config.h @@ -438,17 +438,6 @@ #define OPENTHREAD_CONFIG_POWER_CALIBRATION_ENABLE 0 #endif -/** - * @def OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE - * - * In Zephyr, power calibration is handled by Radio Driver, so it can't be handled on OT level. - * - */ -#ifndef OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE -#define OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE 0 -#endif - - /** * @def OPENTHREAD_CONFIG_RADIO_STATS * diff --git a/modules/openthread/platform/radio.c b/modules/openthread/platform/radio.c index 631d00bdca6f49b..480907380a27c53 100644 --- a/modules/openthread/platform/radio.c +++ b/modules/openthread/platform/radio.c @@ -384,13 +384,8 @@ void transmit_message(struct k_work *tx_job) channel = sTransmitFrame.mChannel; - radio_api->set_channel(radio_dev, sTransmitFrame.mChannel); - -#if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER) - net_pkt_set_ieee802154_txpwr(tx_pkt, get_transmit_power_for_channel(channel)); -#else + radio_api->set_channel(radio_dev, channel); radio_api->set_txpower(radio_dev, get_transmit_power_for_channel(channel)); -#endif /* CONFIG_IEEE802154_SELECTIVE_TXPOWER */ net_pkt_set_ieee802154_frame_secured(tx_pkt, sTransmitFrame.mInfo.mTxInfo.mIsSecurityProcessed); diff --git a/samples/bluetooth/hci_uart_async/boards/nrf52_bsim.overlay b/samples/bluetooth/hci_uart_async/boards/nrf52_bsim.overlay new file mode 100644 index 000000000000000..adef7109b3c9f96 --- /dev/null +++ b/samples/bluetooth/hci_uart_async/boards/nrf52_bsim.overlay @@ -0,0 +1 @@ +/* Purposely empty. To avoid using the one provided by the application */ diff --git a/samples/bluetooth/peripheral_hr/src/main.c b/samples/bluetooth/peripheral_hr/src/main.c index addee9bf92ed6c4..135f41667e21441 100644 --- a/samples/bluetooth/peripheral_hr/src/main.c +++ b/samples/bluetooth/peripheral_hr/src/main.c @@ -22,6 +22,8 @@ #include #include +static bool hrf_ntf_enabled; + 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, @@ -49,6 +51,25 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { .disconnected = disconnected, }; +static void hrs_ntf_changed(bool enabled) +{ + hrf_ntf_enabled = enabled; + + printk("HRS notification status changed: %s\n", enabled ? "enabled" : "disabled"); +} + +static struct bt_hrs_cb hrs_cb = { + .ntf_changed = hrs_ntf_changed, +}; + +/** @brief Heart rate service callback register + * + * This function will register callbacks that will be called in + * certain events related to Heart rate service. + * + * @param cb Pointer to callbacks structure + */ + static void bt_ready(void) { int err; @@ -100,7 +121,9 @@ static void hrs_notify(void) heartrate = 90U; } - bt_hrs_notify(heartrate); + if (hrf_ntf_enabled) { + bt_hrs_notify(heartrate); + } } int main(void) @@ -117,6 +140,7 @@ int main(void) bt_conn_auth_cb_register(&auth_cb_display); + bt_hrs_cb_register(&hrs_cb); /* Implement notification. At the moment there is no suitable way * of starting delayed work so we do it here */ diff --git a/samples/bluetooth/public_broadcast_sink/CMakeLists.txt b/samples/bluetooth/public_broadcast_sink/CMakeLists.txt new file mode 100644 index 000000000000000..74bed078bddb843 --- /dev/null +++ b/samples/bluetooth/public_broadcast_sink/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(pbp_broadcast_sink) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/public_broadcast_sink/Kconfig.sysbuild b/samples/bluetooth/public_broadcast_sink/Kconfig.sysbuild new file mode 100644 index 000000000000000..f434010f81d27ce --- /dev/null +++ b/samples/bluetooth/public_broadcast_sink/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" + default "nrf5340_audio_dk_nrf5340_cpunet" if $(BOARD) = "nrf5340_audio_dk_nrf5340_cpuapp" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/public_broadcast_sink/README.rst b/samples/bluetooth/public_broadcast_sink/README.rst new file mode 100644 index 000000000000000..5f47bcd05abafdf --- /dev/null +++ b/samples/bluetooth/public_broadcast_sink/README.rst @@ -0,0 +1,77 @@ +.. zephyr:code-sample:: bluetooth_public_broadcast_sink + :name: Bluetooth: Public Broadcast Sink + :relevant-api: bluetooth + + Bluetooth: Public Broadcast Sink + +Overview +******** + +Application demonstrating the LE Public Broadcast Profile sink functionality. +Starts by scanning for LE Audio broadcast sources and then synchronizes to +the first found source which defines a Public Broadcast Announcement including +a High Quality Public Broadcast Audio Stream configuration. + +This sample can be found under +:zephyr_file:`samples/bluetooth/public_broadcast_sink` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/public_broadcast_sink/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/public_broadcast_sink/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/public_broadcast_sink/ + :board: nrf5340bsim_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/public_broadcast_sink/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/public_broadcast_sink/overlay-bt_ll_sw_split.conf b/samples/bluetooth/public_broadcast_sink/overlay-bt_ll_sw_split.conf new file mode 100644 index 000000000000000..e336dae38e1f15b --- /dev/null +++ b/samples/bluetooth/public_broadcast_sink/overlay-bt_ll_sw_split.conf @@ -0,0 +1,16 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Enable support for Broadcast ISO Sync +CONFIG_BT_CTLR_SYNC_ISO=y + +# Supports the highest SDU size required by any BAP LC3 presets (155) +CONFIG_BT_CTLR_SYNC_ISO_PDU_LEN_MAX=155 + +# Supports the highest advertising data that is set in a single HCI command in +# Zephyr Bluetooth Controller +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 + +# Number of supported streams +CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 +CONFIG_BT_CTLR_ISOAL_SINKS=2 diff --git a/samples/bluetooth/public_broadcast_sink/prj.conf b/samples/bluetooth/public_broadcast_sink/prj.conf new file mode 100644 index 000000000000000..0feae717a7777a3 --- /dev/null +++ b/samples/bluetooth/public_broadcast_sink/prj.conf @@ -0,0 +1,34 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_PAC_SNK=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_AUDIO=y +CONFIG_UTF8=y + +CONFIG_BT_SMP=y +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y +CONFIG_BT_L2CAP_TX_BUF_COUNT=20 +CONFIG_BT_HCI_ACL_FLOW_CONTROL=n +CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE=196 + +# CAP +CONFIG_BT_CAP_ACCEPTOR=y + +# BAP support +CONFIG_BT_BAP_SCAN_DELEGATOR=y +CONFIG_BT_BAP_BROADCAST_SINK=y +CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT=1 +CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT=1 + +# Support an ISO channel per ASE +CONFIG_BT_ISO_MAX_CHAN=2 + +# Sink PAC Location Support +CONFIG_BT_PAC_SNK_LOC=y + +# Generic config +CONFIG_BT_EXT_ADV=y +CONFIG_BT_DEVICE_NAME="PBP Broadcast Sink" + +# PBP Support +CONFIG_BT_PBP=y diff --git a/samples/bluetooth/public_broadcast_sink/sample.yaml b/samples/bluetooth/public_broadcast_sink/sample.yaml new file mode 100644 index 000000000000000..8b81f4cc36456df --- /dev/null +++ b/samples/bluetooth/public_broadcast_sink/sample.yaml @@ -0,0 +1,27 @@ +sample: + description: Bluetooth Low Energy Audio PBP Broadcast Sink sample + name: Bluetooth Low Energy Audio PBP Broadcast Sink sample +tests: + sample.bluetooth.public_broadcast_sink: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk_nrf5340_cpuapp + - nrf5340bsim_nrf5340_cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk_nrf5340_cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.public_broadcast_sink.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk_nrf52820 + - nrf52833dk_nrf52833 + integration_platforms: + - nrf52_bsim + - nrf52833dk_nrf52833 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/public_broadcast_sink/src/main.c b/samples/bluetooth/public_broadcast_sink/src/main.c new file mode 100644 index 000000000000000..1331ffbededcb92 --- /dev/null +++ b/samples/bluetooth/public_broadcast_sink/src/main.c @@ -0,0 +1,436 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AVAILABLE_SINK_CONTEXT (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) + +#define SEM_TIMEOUT K_SECONDS(10) +#define PA_SYNC_SKIP 5 +#define SYNC_RETRY_COUNT 6 /* similar to retries for connections */ +#define INVALID_BROADCAST_ID 0xFFFFFFFF + +static bool pbs_found; +static uint8_t meta[CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE]; + +static K_SEM_DEFINE(sem_pa_synced, 0U, 1U); +static K_SEM_DEFINE(sem_base_received, 0U, 1U); +static K_SEM_DEFINE(sem_syncable, 0U, 1U); +static K_SEM_DEFINE(sem_pa_sync_lost, 0U, 1U); + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, + struct net_buf_simple *ad); + +static void broadcast_scan_timeout(void); + +static void broadcast_pa_synced(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info); + +static void broadcast_pa_recv(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_recv_info *info, + struct net_buf_simple *buf); + +static void broadcast_pa_terminated(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_term_info *info); + +static struct bt_le_scan_cb broadcast_scan_cb = { + .recv = broadcast_scan_recv, + .timeout = broadcast_scan_timeout +}; + +static struct bt_le_per_adv_sync_cb broadcast_sync_cb = { + .synced = broadcast_pa_synced, + .recv = broadcast_pa_recv, + .term = broadcast_pa_terminated, +}; + +static struct bt_bap_broadcast_sink *broadcast_sink; +static uint32_t bcast_id; +static struct bt_le_per_adv_sync *bcast_pa_sync; + +static struct bt_bap_stream streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; +struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)]; + +static const struct bt_audio_codec_cap codec = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_LC3_FREQ_48KHZ, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 60u, 1u, (BT_AUDIO_CONTEXT_TYPE_MEDIA)); + +/* Create a mask for the maximum BIS we can sync to using the number of streams + * we have. We add an additional 1 since the bis indexes start from 1 and not + * 0. + */ +static const uint32_t bis_index_mask = BIT_MASK(ARRAY_SIZE(streams) + 1U); +static uint32_t bis_index_bitfield; + +static void stream_started_cb(struct bt_bap_stream *stream) +{ + printk("Stream %p started\n", stream); +} + +static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + printk("Stream %p stopped with reason 0x%02X\n", stream, reason); +} + +static void stream_recv_cb(struct bt_bap_stream *stream, + const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + static uint32_t recv_cnt; + + recv_cnt++; + if ((recv_cnt % 20U) == 0U) { + printk("Received %u total ISO packets\n", recv_cnt); + } +} + +static struct bt_bap_stream_ops stream_ops = { + .started = stream_started_cb, + .stopped = stream_stopped_cb, + .recv = stream_recv_cb +}; + +static struct bt_pacs_cap cap = { + .codec_cap = &codec, +}; + +static uint16_t interval_to_sync_timeout(uint16_t interval) +{ + uint32_t interval_ms; + uint16_t timeout; + + /* Ensure that the following calculation does not overflow silently */ + __ASSERT(SYNC_RETRY_COUNT < 10, "SYNC_RETRY_COUNT shall be less than 10"); + + /* Add retries and convert to unit in 10's of ms */ + interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(interval); + timeout = (interval_ms * SYNC_RETRY_COUNT) / 10; + + /* Enforce restraints */ + timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT); + + return timeout; +} + +static void sync_broadcast_pa(const struct bt_le_scan_recv_info *info, + uint32_t broadcast_id) +{ + struct bt_le_per_adv_sync_param param; + int err; + + /* Unregister the callbacks to prevent broadcast_scan_recv to be called again */ + bt_le_scan_cb_unregister(&broadcast_scan_cb); + + err = bt_le_scan_stop(); + if (err != 0) { + printk("Could not stop scan: %d", err); + } + + bt_addr_le_copy(¶m.addr, info->addr); + param.options = 0; + param.sid = info->sid; + param.skip = PA_SYNC_SKIP; + param.timeout = interval_to_sync_timeout(info->interval); + err = bt_le_per_adv_sync_create(¶m, &bcast_pa_sync); + + if (err != 0) { + printk("Could not sync to PA: %d", err); + } else { + bcast_id = broadcast_id; + } +} + +static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) +{ + uint32_t *broadcast_id = user_data; + struct bt_uuid_16 adv_uuid; + enum bt_pbp_announcement_feature source_features = 0U; + + memset(meta, 0, ARRAY_SIZE(meta)); + + if (data->type != BT_DATA_SVC_DATA16) { + return true; + } + + if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + return true; + } + + if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) { + *broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); + return true; + } + + if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_PBA)) { + bt_pbp_parse_announcement(data, &source_features, meta); + if (!(source_features & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY)) { + /* This is a Standard Quality Public Broadcast Audio stream */ + printk("This is a Standard Quality Public Broadcast Audio stream\n"); + pbs_found = false; + + return true; + } + printk("Found Suitable Public Broadcast Announcement\n"); + pbs_found = true; + + /** + * Continue parsing if Broadcast Audio Announcement Service + * was not found. + */ + if (*broadcast_id == INVALID_BROADCAST_ID) { + return true; + } + + return false; + } + + return true; +} + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, + struct net_buf_simple *ad) +{ + uint32_t broadcast_id; + + pbs_found = false; + + /* We are only interested in non-connectable periodic advertisers */ + if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) || info->interval == 0) { + return; + } + + broadcast_id = INVALID_BROADCAST_ID; + bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)&broadcast_id); + + if ((broadcast_id != INVALID_BROADCAST_ID) && pbs_found) { + sync_broadcast_pa(info, broadcast_id); + } +} + +static void broadcast_scan_timeout(void) +{ + printk("Broadcast scan timed out\n"); +} + +static bool pa_decode_base(struct bt_data *data, void *user_data) +{ + const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); + uint32_t base_bis_index_bitfield = 0U; + int err; + + /* Base is NULL if the data does not contain a valid BASE */ + if (base == NULL) { + return true; + } + + err = bt_bap_base_get_bis_indexes(base, &base_bis_index_bitfield); + if (err != 0) { + return false; + } + + bis_index_bitfield = base_bis_index_bitfield & bis_index_mask; + k_sem_give(&sem_base_received); + + return false; +} + +static void broadcast_pa_recv(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_recv_info *info, + struct net_buf_simple *buf) +{ + bt_data_parse(buf, pa_decode_base, NULL); +} + +static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted) +{ + k_sem_give(&sem_syncable); +} + +static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base, + size_t base_size) +{ + k_sem_give(&sem_base_received); +} + +static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = { + .syncable = syncable_cb, + .base_recv = base_recv_cb, +}; + +static void broadcast_pa_synced(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info) +{ + if (sync == bcast_pa_sync) { + printk("PA sync %p synced for broadcast sink with broadcast ID 0x%06X\n", + sync, bcast_id); + + k_sem_give(&sem_pa_synced); + } +} + +static void broadcast_pa_terminated(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_term_info *info) +{ + if (sync == bcast_pa_sync) { + printk("PA sync %p lost with reason %u\n", sync, info->reason); + bcast_pa_sync = NULL; + + k_sem_give(&sem_pa_sync_lost); + } +} + +static int reset(void) +{ + if (broadcast_sink != NULL) { + int err = bt_bap_broadcast_sink_delete(broadcast_sink); + + if (err) { + printk("Deleting broadcast sink failed (err %d)\n", err); + + return err; + } + + broadcast_sink = NULL; + } + k_sem_reset(&sem_pa_synced); + k_sem_reset(&sem_base_received); + k_sem_reset(&sem_syncable); + k_sem_reset(&sem_pa_sync_lost); + + return 0; +} + +int bap_broadcast_sink_init(void) +{ + int err; + + bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs); + bt_le_per_adv_sync_cb_register(&broadcast_sync_cb); + + err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); + if (err) { + printk("Capability register failed (err %d)\n", err); + + return err; + } + + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + streams[i].ops = &stream_ops; + } + + for (size_t i = 0U; i < ARRAY_SIZE(streams_p); i++) { + streams_p[i] = &streams[i]; + } + + return 0; +} + +int bap_broadcast_sink_run(void) +{ + while (true) { + int err = reset(); + + if (err != 0) { + printk("Resetting failed: %d - Aborting\n", err); + + return err; + } + + /* Register callbacks */ + bt_le_scan_cb_register(&broadcast_scan_cb); + + /* Start scanning */ + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err) { + printk("Scan start failed (err %d)\n", err); + + return err; + } + + /* Wait until a suitable source is found */ + err = k_sem_take(&sem_pa_synced, K_FOREVER); + printk("Broadcast source PA synced, waiting for BASE\n"); + + /* Wait for BASE decode */ + err = k_sem_take(&sem_base_received, SEM_TIMEOUT); + if (err != 0) { + printk("sem_base_received timed out\n"); + + return err; + } + + /* Create broadcast sink */ + printk("BASE received, creating broadcast sink\n"); + err = bt_bap_broadcast_sink_create(bcast_pa_sync, bcast_id, &broadcast_sink); + if (err != 0) { + printk("bt_bap_broadcast_sink_create failed: %d\n", err); + + return err; + } + + k_sem_take(&sem_syncable, SEM_TIMEOUT); + if (err != 0) { + printk("sem_syncable timed out\n"); + + return err; + } + + /* Sync to broadcast source */ + printk("Syncing to broadcast\n"); + err = bt_bap_broadcast_sink_sync(broadcast_sink, bis_index_bitfield, + streams_p, NULL); + if (err != 0) { + printk("Unable to sync to broadcast source: %d\n", err); + + return err; + } + + k_sem_take(&sem_pa_sync_lost, K_FOREVER); + } + + return 0; +} + +int main(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + printk("Bluetooth init failed (err %d)\n", err); + + return err; + } + printk("Bluetooth initialized\n"); + + printk("Initializing BAP Broadcast Sink\n"); + err = bap_broadcast_sink_init(); + if (err != 0) { + return err; + } + + err = bap_broadcast_sink_run(); + if (err != 0) { + return err; + } + + return 0; +} diff --git a/samples/bluetooth/public_broadcast_sink/sysbuild.cmake b/samples/bluetooth/public_broadcast_sink/sysbuild.cmake new file mode 100644 index 000000000000000..2523aac8ea76f16 --- /dev/null +++ b/samples/bluetooth/public_broadcast_sink/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# 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}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/bluetooth/public_broadcast_source/CMakeLists.txt b/samples/bluetooth/public_broadcast_source/CMakeLists.txt new file mode 100644 index 000000000000000..6331703e2d89a5b --- /dev/null +++ b/samples/bluetooth/public_broadcast_source/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(public_broadcast_source) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/public_broadcast_source/Kconfig.sysbuild b/samples/bluetooth/public_broadcast_source/Kconfig.sysbuild new file mode 100644 index 000000000000000..f434010f81d27ce --- /dev/null +++ b/samples/bluetooth/public_broadcast_source/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk_nrf5340_cpunet" if $(BOARD) = "nrf5340dk_nrf5340_cpuapp" + default "nrf5340_audio_dk_nrf5340_cpunet" if $(BOARD) = "nrf5340_audio_dk_nrf5340_cpuapp" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/public_broadcast_source/README.rst b/samples/bluetooth/public_broadcast_source/README.rst new file mode 100644 index 000000000000000..9111cd3f614c13c --- /dev/null +++ b/samples/bluetooth/public_broadcast_source/README.rst @@ -0,0 +1,77 @@ +.. zephyr:code-sample:: bluetooth_public_broadcast_source + :name: Bluetooth: Public Broadcast Source + :relevant-api: bluetooth + + Bluetooth: Public Broadcast Source + +Overview +******** + +Application demonstrating the LE Public Broadcast Profile source functionality. +Will start advertising extended advertising and includes a Broadcast Audio Announcement. +The advertised broadcast audio stream quality will cycle between high and standard quality +every 15 seconds. + +This sample can be found under +:zephyr_file:`samples/bluetooth/public_broadcast_source` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/public_broadcast_source/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/public_broadcast_source/ + :board: nrf5340dk_nrf5340_cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/public_broadcast_source/ + :board: nrf5340bsim_nrf5340_cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/public_broadcast_source/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf b/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf new file mode 100644 index 000000000000000..c73ff9c3ea9b88f --- /dev/null +++ b/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf @@ -0,0 +1,24 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Zephyr Controller tested maximum advertising data that can be set in a single HCI command +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 + +# Enable support for Broadcast ISO in Zephyr Bluetooth Controller +CONFIG_BT_CTLR_ADV_ISO=y + +# Sufficient ISO PDU length for any BAP LC3 presets (155) +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=155 + +# Number of supported streams +CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 +CONFIG_BT_CTLR_ISOAL_SOURCES=2 + +# FIXME: Host needs CONFIG_BT_ISO_TX_MTU + 4 bytes for sequence number, and optionally +# additional + 4 bytes for timestamp when not using BT_ISO_TIMESTAMP_NONE in bt_iso_chan_send(), +# otherwise Host tries to fragment ISO data. +# When Host is fixed, CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE can inherit the +# CONFIG_BT_ISO_TX_MTU value. +# +# Supports the highest SDU size required by any BAP LC3 presets (155) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 diff --git a/samples/bluetooth/public_broadcast_source/prj.conf b/samples/bluetooth/public_broadcast_source/prj.conf new file mode 100644 index 000000000000000..ca7d3f38261b781 --- /dev/null +++ b/samples/bluetooth/public_broadcast_source/prj.conf @@ -0,0 +1,26 @@ +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_AUDIO=y +CONFIG_BT_PERIPHERAL=y + +CONFIG_BT_ISO_MAX_CHAN=2 +CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=2 +CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=2 +CONFIG_BT_ISO_TX_BUF_COUNT=4 +CONFIG_BT_HCI_ACL_FLOW_CONTROL=n + +# PBP support +CONFIG_BT_PBP=y + +# CAP support +CONFIG_BT_CAP_INITIATOR=y + +# BAP support +CONFIG_BT_BAP_BROADCAST_SOURCE=y +CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=1 +CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=1 + +CONFIG_BT_EXT_ADV=y +CONFIG_BT_DEVICE_NAME="PBS" diff --git a/samples/bluetooth/public_broadcast_source/sample.yaml b/samples/bluetooth/public_broadcast_source/sample.yaml new file mode 100644 index 000000000000000..eb2bd5dc79b909e --- /dev/null +++ b/samples/bluetooth/public_broadcast_source/sample.yaml @@ -0,0 +1,27 @@ +sample: + description: Bluetooth Low Energy Public Broadcast Source sample + name: Bluetooth Low Energy Public Broadcast Source sample +tests: + sample.bluetooth.public_broadcast_source: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk_nrf5340_cpuapp + - nrf5340bsim_nrf5340_cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk_nrf5340_cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.public_broadcast_source.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk_nrf52820 + - nrf52833dk_nrf52833 + integration_platforms: + - nrf52_bsim + - nrf52833dk_nrf52833 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/public_broadcast_source/src/main.c b/samples/bluetooth/public_broadcast_source/src/main.c new file mode 100644 index 000000000000000..c719810e243586d --- /dev/null +++ b/samples/bluetooth/public_broadcast_source/src/main.c @@ -0,0 +1,424 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BROADCAST_ENQUEUE_COUNT 2U + +/* PBS ASCII text */ +#define PBS_DEMO 'P', 'B', 'P' + +NET_BUF_POOL_FIXED_DEFINE(tx_pool, + (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT), + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); + +static K_SEM_DEFINE(sem_broadcast_started, 0, 1); +static K_SEM_DEFINE(sem_broadcast_stopped, 0, 1); + +static struct bt_cap_stream broadcast_source_stream; +static struct bt_cap_stream *broadcast_stream; + +static uint8_t bis_codec_data[] = {BT_AUDIO_CODEC_DATA( + BT_AUDIO_CODEC_CONFIG_LC3_FREQ, BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ))}; + + +const uint8_t pba_metadata[] = { + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, PBS_DEMO) +}; + +static uint8_t appearance_addata[] = { + BT_BYTES_LIST_LE16(BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE) +}; + +static const char broadcast_name[] = "PBP Source Demo"; + +static struct bt_bap_lc3_preset broadcast_preset_48_2_1 = + BT_BAP_LC3_UNICAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT, + BT_AUDIO_CONTEXT_TYPE_MEDIA); + +struct bt_cap_initiator_broadcast_stream_param stream_params; +struct bt_cap_initiator_broadcast_subgroup_param subgroup_param; +struct bt_cap_initiator_broadcast_create_param create_param; +struct bt_cap_broadcast_source *broadcast_source; +struct bt_le_ext_adv *ext_adv; + +static void broadcast_started_cb(struct bt_bap_stream *stream) +{ + printk("Stream %p started\n", stream); + k_sem_give(&sem_broadcast_started); +} + +static void broadcast_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + if (reason == BT_HCI_ERR_LOCALHOST_TERM_CONN) { + printk("Stream %p ended\n", stream); + } else { + printk("Stream %p stopped with reason 0x%02X\n", stream, reason); + } + + k_sem_give(&sem_broadcast_stopped); +} + +static void broadcast_sent_cb(struct bt_bap_stream *stream) +{ + static uint8_t mock_data[CONFIG_BT_ISO_TX_MTU]; + static bool mock_data_initialized; + static uint32_t seq_num; + struct net_buf *buf; + int ret; + + if (broadcast_preset_48_2_1.qos.sdu > CONFIG_BT_ISO_TX_MTU) { + printk("Invalid SDU %u for the MTU: %d", broadcast_preset_48_2_1.qos.sdu, + CONFIG_BT_ISO_TX_MTU); + + return; + } + + if (!mock_data_initialized) { + for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) { + /* Initialize mock data */ + mock_data[i] = (uint8_t)i; + } + mock_data_initialized = true; + } + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + if (buf == NULL) { + printk("Could not allocate buffer when sending on %p\n", stream); + + return; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + net_buf_add_mem(buf, mock_data, broadcast_preset_48_2_1.qos.sdu); + ret = bt_bap_stream_send(stream, buf, seq_num++, BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + /* This will end broadcasting on this stream. */ + net_buf_unref(buf); + + return; + } +} + +static struct bt_bap_stream_ops broadcast_stream_ops = { + .started = broadcast_started_cb, + .stopped = broadcast_stopped_cb, + .sent = broadcast_sent_cb +}; + +static int setup_extended_adv(struct bt_le_ext_adv **adv) +{ + int err; + + /* Create a non-connectable non-scannable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN_NAME, NULL, adv); + if (err != 0) { + printk("Unable to create extended advertising set: %d\n", err); + + return err; + } + + /* Set periodic advertising parameters */ + err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT); + if (err) { + printk("Failed to set periodic advertising parameters: %d\n", err); + + return err; + } + + return 0; +} + +static int setup_extended_adv_data(struct bt_cap_broadcast_source *source, + struct bt_le_ext_adv *adv) +{ + /* Broadcast Audio Streaming Endpoint advertising data */ + NET_BUF_SIMPLE_DEFINE(ad_buf, + BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); + NET_BUF_SIMPLE_DEFINE(base_buf, 128); + NET_BUF_SIMPLE_DEFINE(pbp_ad_buf, BT_UUID_SIZE_16 + 1 + ARRAY_SIZE(pba_metadata)); + static enum bt_pbp_announcement_feature pba_params; + struct bt_data ext_ad[4]; + struct bt_data per_ad; + uint32_t broadcast_id; + int err; + + err = bt_cap_initiator_broadcast_get_id(source, &broadcast_id); + if (err != 0) { + printk("Unable to get broadcast ID: %d\n", err); + + return err; + } + + /* Setup extended advertising data */ + ext_ad[0].type = BT_DATA_GAP_APPEARANCE; + ext_ad[0].data_len = 2; + ext_ad[0].data = appearance_addata; + /* Broadcast name AD Type */ + ext_ad[1].type = BT_DATA_BROADCAST_NAME; + ext_ad[1].data_len = ARRAY_SIZE(broadcast_name); + ext_ad[1].data = broadcast_name; + /* Broadcast Audio Announcement */ + net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); + net_buf_simple_add_le24(&ad_buf, broadcast_id); + ext_ad[2].type = BT_DATA_SVC_DATA16; + ext_ad[2].data_len = ad_buf.len + sizeof(ext_ad[2].type); + ext_ad[2].data = ad_buf.data; + + /** + * Create a Public Broadcast Announcement + * Cycle between high and standard quality public broadcast audio. + */ + if (pba_params & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY) { + pba_params = 0; + pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_STANDARD_QUALITY; + printk("Starting stream with standard quality!\n"); + } else { + pba_params = 0; + pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY; + printk("Starting stream with high quality!\n"); + } + err = bt_pbp_get_announcement(&pba_metadata[1], ARRAY_SIZE(pba_metadata) - 1, + pba_params, &pbp_ad_buf); + if (err != 0) { + printk("Failed to create public broadcast announcement!: %d\n", err); + + return err; + } + ext_ad[3].type = BT_DATA_SVC_DATA16; + ext_ad[3].data_len = pbp_ad_buf.len; + ext_ad[3].data = pbp_ad_buf.data; + err = bt_le_ext_adv_set_data(adv, ext_ad, ARRAY_SIZE(ext_ad), NULL, 0); + if (err != 0) { + printk("Failed to set extended advertising data: %d\n", err); + + return err; + } + + /* Setup periodic advertising data */ + err = bt_cap_initiator_broadcast_get_base(source, &base_buf); + if (err != 0) { + printk("Failed to get encoded BASE: %d\n", err); + + return err; + } + + per_ad.type = BT_DATA_SVC_DATA16; + per_ad.data_len = base_buf.len; + per_ad.data = base_buf.data; + err = bt_le_per_adv_set_data(adv, &per_ad, 1); + if (err != 0) { + printk("Failed to set periodic advertising data: %d\n", err); + + return err; + } + + return 0; +} + +static int start_extended_adv(struct bt_le_ext_adv *adv) +{ + int err; + + /* Start extended advertising */ + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err) { + printk("Failed to start extended advertising: %d\n", err); + + return err; + } + + /* Enable Periodic Advertising */ + err = bt_le_per_adv_start(adv); + if (err) { + printk("Failed to enable periodic advertising: %d\n", err); + + return err; + } + + return 0; +} + +static int stop_and_delete_extended_adv(struct bt_le_ext_adv *adv) +{ + int err; + + /* Stop extended advertising */ + err = bt_le_per_adv_stop(adv); + if (err) { + printk("Failed to stop periodic advertising: %d\n", err); + + return err; + } + + err = bt_le_ext_adv_stop(adv); + if (err) { + printk("Failed to stop extended advertising: %d\n", err); + + return err; + } + + err = bt_le_ext_adv_delete(adv); + if (err) { + printk("Failed to delete extended advertising: %d\n", err); + + return err; + } + + return 0; +} + +static int reset(void) +{ + k_sem_reset(&sem_broadcast_started); + k_sem_reset(&sem_broadcast_stopped); + + return 0; +} + +int cap_initiator_init(void) +{ + if (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE)) { + broadcast_stream = &broadcast_source_stream; + bt_bap_stream_cb_register(&broadcast_stream->bap_stream, &broadcast_stream_ops); + } + + return 0; +} + +void cap_initiator_setup(void) +{ + int err; + + stream_params.stream = &broadcast_source_stream; + stream_params.data_len = ARRAY_SIZE(bis_codec_data); + stream_params.data = bis_codec_data; + + subgroup_param.stream_count = 1U; + subgroup_param.stream_params = &stream_params; + subgroup_param.codec_cfg = &broadcast_preset_48_2_1.codec_cfg; + + create_param.subgroup_count = 1U; + create_param.subgroup_params = &subgroup_param; + create_param.qos = &broadcast_preset_48_2_1.qos; + create_param.packing = BT_ISO_PACKING_SEQUENTIAL; + create_param.encryption = false; + + while (true) { + err = reset(); + if (err != 0) { + printk("Resetting failed: %d - Aborting\n", err); + + return; + } + + err = setup_extended_adv(&ext_adv); + if (err != 0) { + printk("Unable to setup extended advertiser: %d\n", err); + + return; + } + + err = bt_cap_initiator_broadcast_audio_create(&create_param, &broadcast_source); + if (err != 0) { + printk("Unable to create broadcast source: %d\n", err); + + return; + } + + err = bt_cap_initiator_broadcast_audio_start(broadcast_source, ext_adv); + if (err != 0) { + printk("Unable to start broadcast source: %d\n", err); + + return; + } + + err = setup_extended_adv_data(broadcast_source, ext_adv); + if (err != 0) { + printk("Unable to setup extended advertising data: %d\n", err); + + return; + } + + err = start_extended_adv(ext_adv); + if (err != 0) { + printk("Unable to start extended advertiser: %d\n", err); + + return; + } + k_sem_take(&sem_broadcast_started, K_FOREVER); + + /* Initialize sending */ + for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) { + broadcast_sent_cb(&broadcast_stream->bap_stream); + } + + /* Keeping running for a little while */ + k_sleep(K_SECONDS(15)); + + err = bt_cap_initiator_broadcast_audio_stop(broadcast_source); + if (err != 0) { + printk("Failed to stop broadcast source: %d\n", err); + + return; + } + + k_sem_take(&sem_broadcast_stopped, K_FOREVER); + err = bt_cap_initiator_broadcast_audio_delete(broadcast_source); + if (err != 0) { + printk("Failed to stop broadcast source: %d\n", err); + + return; + } + broadcast_source = NULL; + + err = stop_and_delete_extended_adv(ext_adv); + if (err != 0) { + printk("Failed to stop and delete extended advertising: %d\n", err); + + return; + } + } +} + + +int main(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + printk("Bluetooth enable failed (err %d)\n", err); + + return err; + } + + printk("Bluetooth initialized\n"); + + /* Initialize CAP Initiator */ + err = cap_initiator_init(); + if (err != 0) { + return err; + } + + printk("CAP initialized\n"); + + /* Configure and start broadcast stream */ + cap_initiator_setup(); + + return 0; +} diff --git a/samples/bluetooth/public_broadcast_source/sysbuild.cmake b/samples/bluetooth/public_broadcast_source/sysbuild.cmake new file mode 100644 index 000000000000000..d3bf7be5b6c36ff --- /dev/null +++ b/samples/bluetooth/public_broadcast_source/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(NOT("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "")) + # 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}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/bluetooth/tmap_bms/prj.conf b/samples/bluetooth/tmap_bms/prj.conf index ab3641a7a0fc0d6..be8acce18802d4d 100644 --- a/samples/bluetooth/tmap_bms/prj.conf +++ b/samples/bluetooth/tmap_bms/prj.conf @@ -1,3 +1,5 @@ +CONFIG_MAIN_STACK_SIZE=2048 + CONFIG_BT=y CONFIG_LOG=y CONFIG_BT_PERIPHERAL=y diff --git a/samples/bluetooth/tmap_bms/src/cap_initiator.c b/samples/bluetooth/tmap_bms/src/cap_initiator.c index af946f8ba945e4e..1e50977eab52126 100644 --- a/samples/bluetooth/tmap_bms/src/cap_initiator.c +++ b/samples/bluetooth/tmap_bms/src/cap_initiator.c @@ -16,7 +16,7 @@ #include #define BROADCAST_ENQUEUE_COUNT 2U -#define MOCK_CCID 0xAB + NET_BUF_POOL_FIXED_DEFINE(tx_pool, (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT), BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); @@ -32,8 +32,7 @@ static uint8_t bis_codec_data[] = {BT_AUDIO_CODEC_DATA( static const uint8_t new_metadata[] = { BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, - BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_MEDIA)), - BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, MOCK_CCID), + BT_BYTES_LIST_LE16(BT_AUDIO_CONTEXT_TYPE_MEDIA)) }; static struct bt_bap_lc3_preset broadcast_preset_48_2_1 = @@ -60,6 +59,7 @@ static void broadcast_started_cb(struct bt_bap_stream *stream) static void broadcast_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) { printk("Stream %p stopped with reason 0x%02X\n", stream, reason); + k_sem_give(&sem_broadcast_stopped); } @@ -151,11 +151,13 @@ static int setup_extended_adv_data(struct bt_cap_broadcast_source *source, ext_ad[0].type = BT_DATA_SVC_DATA16; ext_ad[0].data_len = ARRAY_SIZE(tmap_addata); ext_ad[0].data = tmap_addata; + /* Broadcast Audio Announcement */ net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); net_buf_simple_add_le24(&ad_buf, broadcast_id); ext_ad[1].type = BT_DATA_SVC_DATA16; ext_ad[1].data_len = ad_buf.len + sizeof(ext_ad[1].type); ext_ad[1].data = ad_buf.data; + err = bt_le_ext_adv_set_data(adv, ext_ad, ARRAY_SIZE(ext_ad), NULL, 0); if (err != 0) { printk("Failed to set extended advertising data: %d\n", err); diff --git a/samples/boards/nrf/nrfx/Kconfig b/samples/boards/nrf/nrfx/Kconfig index 0d54067202a2276..a46af347ba932e3 100644 --- a/samples/boards/nrf/nrfx/Kconfig +++ b/samples/boards/nrf/nrfx/Kconfig @@ -2,9 +2,19 @@ # SPDX-License-Identifier: Apache-2.0 config NRFX_DPPI - default HAS_HW_NRF_DPPIC + default $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_DPPIC)) config NRFX_PPI - default HAS_HW_NRF_PPI + default $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_PPI)) + +config NRFX_GPIOTE0 + default y if SOC_SERIES_NRF51X || \ + SOC_SERIES_NRF52X || \ + (SOC_SERIES_NRF53X && !TRUSTED_EXECUTION_NONSECURE) || \ + (SOC_SERIES_NRF91X && !TRUSTED_EXECUTION_NONSECURE) + +config NRFX_GPIOTE1 + default y if (SOC_SERIES_NRF53X && TRUSTED_EXECUTION_NONSECURE) || \ + (SOC_SERIES_NRF91X && TRUSTED_EXECUTION_NONSECURE) source "Kconfig.zephyr" diff --git a/samples/boards/nrf/nrfx/prj.conf b/samples/boards/nrf/nrfx/prj.conf index 32cbfc3279cccd1..d4f0c29699f8806 100644 --- a/samples/boards/nrf/nrfx/prj.conf +++ b/samples/boards/nrf/nrfx/prj.conf @@ -1,4 +1,3 @@ CONFIG_GPIO=n -CONFIG_NRFX_GPIOTE=y CONFIG_LOG=y CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100 diff --git a/samples/boards/nrf/nrfx/src/main.c b/samples/boards/nrf/nrfx/src/main.c index 615b800545e4863..8b3819f2d8a15c0 100644 --- a/samples/boards/nrf/nrfx/src/main.c +++ b/samples/boards/nrf/nrfx/src/main.c @@ -8,18 +8,22 @@ #include #include -#if defined(DPPI_PRESENT) -#include -#else -#include -#endif #include #include LOG_MODULE_REGISTER(nrfx_sample, LOG_LEVEL_INF); -#define INPUT_PIN DT_GPIO_PIN(DT_ALIAS(sw0), gpios) -#define OUTPUT_PIN DT_GPIO_PIN(DT_ALIAS(led0), gpios) +#define INPUT_PIN NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(sw0), gpios) +#define OUTPUT_PIN NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(led0), gpios) + +#define GPIOTE_INST NRF_DT_GPIOTE_INST(DT_ALIAS(sw0), gpios) +#define GPIOTE_NODE DT_NODELABEL(_CONCAT(gpiote, GPIOTE_INST)) + +BUILD_ASSERT(NRF_DT_GPIOTE_INST(DT_ALIAS(led0), gpios) == GPIOTE_INST, + "Both sw0 and led0 GPIOs must use the same GPIOTE instance"); +BUILD_ASSERT(IS_ENABLED(_CONCAT(CONFIG_, _CONCAT(NRFX_GPIOTE, GPIOTE_INST))), + "NRFX_GPIOTE" STRINGIFY(GPIOTE_INST) " must be enabled in Kconfig"); + static void button_handler(nrfx_gpiote_pin_t pin, nrfx_gpiote_trigger_t trigger, @@ -35,28 +39,28 @@ int main(void) nrfx_err_t err; uint8_t in_channel, out_channel; uint8_t ppi_channel; + const nrfx_gpiote_t gpiote = NRFX_GPIOTE_INSTANCE(GPIOTE_INST); - /* Connect GPIOTE_0 IRQ to nrfx_gpiote_irq_handler */ - IRQ_CONNECT(DT_IRQN(DT_NODELABEL(gpiote)), - DT_IRQ(DT_NODELABEL(gpiote), priority), - nrfx_isr, nrfx_gpiote_irq_handler, 0); + /* Connect GPIOTE instance IRQ to irq handler */ + IRQ_CONNECT(DT_IRQN(GPIOTE_NODE), DT_IRQ(GPIOTE_NODE, priority), nrfx_isr, + NRFX_CONCAT(nrfx_gpiote_, GPIOTE_INST, _irq_handler), 0); /* Initialize GPIOTE (the interrupt priority passed as the parameter * here is ignored, see nrfx_glue.h). */ - err = nrfx_gpiote_init(0); + err = nrfx_gpiote_init(&gpiote, 0); if (err != NRFX_SUCCESS) { LOG_ERR("nrfx_gpiote_init error: 0x%08X", err); return 0; } - err = nrfx_gpiote_channel_alloc(&in_channel); + err = nrfx_gpiote_channel_alloc(&gpiote, &in_channel); if (err != NRFX_SUCCESS) { LOG_ERR("Failed to allocate in_channel, error: 0x%08X", err); return 0; } - err = nrfx_gpiote_channel_alloc(&out_channel); + err = nrfx_gpiote_channel_alloc(&gpiote, &out_channel); if (err != NRFX_SUCCESS) { LOG_ERR("Failed to allocate out_channel, error: 0x%08X", err); return 0; @@ -65,20 +69,22 @@ int main(void) /* Initialize input pin to generate event on high to low transition * (falling edge) and call button_handler() */ - static const nrfx_gpiote_input_config_t input_config = { - .pull = NRF_GPIO_PIN_PULLUP, - }; - const nrfx_gpiote_trigger_config_t trigger_config = { + static const nrf_gpio_pin_pull_t pull_config = NRF_GPIO_PIN_PULLUP; + nrfx_gpiote_trigger_config_t trigger_config = { .trigger = NRFX_GPIOTE_TRIGGER_HITOLO, .p_in_channel = &in_channel, }; static const nrfx_gpiote_handler_config_t handler_config = { .handler = button_handler, }; - err = nrfx_gpiote_input_configure(INPUT_PIN, - &input_config, - &trigger_config, - &handler_config); + nrfx_gpiote_input_pin_config_t input_config = { + .p_pull_config = &pull_config, + .p_trigger_config = &trigger_config, + .p_handler_config = &handler_config + }; + + err = nrfx_gpiote_input_configure(&gpiote, INPUT_PIN, &input_config); + if (err != NRFX_SUCCESS) { LOG_ERR("nrfx_gpiote_input_configure error: 0x%08X", err); return 0; @@ -97,7 +103,7 @@ int main(void) .polarity = NRF_GPIOTE_POLARITY_TOGGLE, .init_val = 1, }; - err = nrfx_gpiote_output_configure(OUTPUT_PIN, + err = nrfx_gpiote_output_configure(&gpiote, OUTPUT_PIN, &output_config, &task_config); if (err != NRFX_SUCCESS) { @@ -105,8 +111,8 @@ int main(void) return 0; } - nrfx_gpiote_trigger_enable(INPUT_PIN, true); - nrfx_gpiote_out_task_enable(OUTPUT_PIN); + nrfx_gpiote_trigger_enable(&gpiote, INPUT_PIN, true); + nrfx_gpiote_out_task_enable(&gpiote, OUTPUT_PIN); LOG_INF("nrfx_gpiote initialized"); @@ -122,8 +128,8 @@ int main(void) * the button is pressed, the LED pin will be toggled. */ nrfx_gppi_channel_endpoints_setup(ppi_channel, - nrfx_gpiote_in_event_address_get(INPUT_PIN), - nrfx_gpiote_out_task_address_get(OUTPUT_PIN)); + nrfx_gpiote_in_event_address_get(&gpiote, INPUT_PIN), + nrfx_gpiote_out_task_address_get(&gpiote, OUTPUT_PIN)); /* Enable the channel. */ nrfx_gppi_channels_enable(BIT(ppi_channel)); diff --git a/samples/drivers/led_ws2812/boards/adafruit_kb2040.conf b/samples/drivers/led_ws2812/boards/adafruit_kb2040.conf new file mode 100644 index 000000000000000..9ccb06fb7bc12e3 --- /dev/null +++ b/samples/drivers/led_ws2812/boards/adafruit_kb2040.conf @@ -0,0 +1 @@ +CONFIG_WS2812_STRIP_RPI_PICO_PIO=y diff --git a/samples/drivers/uart/native_tty/CMakeLists.txt b/samples/drivers/uart/native_tty/CMakeLists.txt index c0fa477a106fc96..528ed22fc56acc0 100644 --- a/samples/drivers/uart/native_tty/CMakeLists.txt +++ b/samples/drivers/uart/native_tty/CMakeLists.txt @@ -4,8 +4,5 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(native_tty) -set(CMAKE_EXPORT_COMPILE_COMMANDS on) -zephyr_compile_options(-fdiagnostics-color=always) - file(GLOB app_sources src/main.c) target_sources(app PRIVATE ${app_sources}) diff --git a/samples/net/gptp/boards/xmc45_relax_kit.conf b/samples/net/gptp/boards/xmc45_relax_kit.conf new file mode 100644 index 000000000000000..720b511fdb9741f --- /dev/null +++ b/samples/net/gptp/boards/xmc45_relax_kit.conf @@ -0,0 +1,2 @@ +CONFIG_NET_TC_TX_COUNT=3 +CONFIG_NET_TC_RX_COUNT=2 diff --git a/samples/net/sockets/dumb_http_server/src/socket_dumb_http.c b/samples/net/sockets/dumb_http_server/src/socket_dumb_http.c index 76b94934df89d47..d9194ca0dd20413 100644 --- a/samples/net/sockets/dumb_http_server/src/socket_dumb_http.c +++ b/samples/net/sockets/dumb_http_server/src/socket_dumb_http.c @@ -40,6 +40,21 @@ static const char content[] = { #endif }; +/* If accept returns an error, then we are probably running + * out of resource. Sleep a small amount of time in order the + * system to cool down. + */ +#define ACCEPT_ERROR_WAIT 100 /* in ms */ + +static void sleep_after_error(unsigned int amount) +{ +#if defined(__ZEPHYR__) + k_msleep(amount); +#else + usleep(amount * 1000U); +#endif +} + int main(void) { int serv; @@ -72,6 +87,7 @@ int main(void) &client_addr_len); if (client < 0) { printf("Error in accept: %d - continuing\n", errno); + sleep_after_error(ACCEPT_ERROR_WAIT); continue; } diff --git a/samples/net/sockets/dumb_http_server_mt/src/main.c b/samples/net/sockets/dumb_http_server_mt/src/main.c index baa295b7f50df35..06f9f0c6e716912 100644 --- a/samples/net/sockets/dumb_http_server_mt/src/main.c +++ b/samples/net/sockets/dumb_http_server_mt/src/main.c @@ -20,6 +20,12 @@ LOG_MODULE_REGISTER(net_dumb_http_srv_mt_sample); #define MY_PORT 8080 +/* If accept returns an error, then we are probably running + * out of resource. Sleep a small amount of time in order the + * system to cool down. + */ +#define ACCEPT_ERROR_WAIT 100 /* in ms */ + #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) #define STACK_SIZE 4096 @@ -268,8 +274,9 @@ static int process_tcp(int *sock, int *accepted) client = accept(*sock, (struct sockaddr *)&client_addr, &client_addr_len); if (client < 0) { - LOG_ERR("Error in accept %d, stopping server", -errno); - return -errno; + LOG_DBG("Error in accept %d, ignored", -errno); + k_msleep(ACCEPT_ERROR_WAIT); + return 0; } slot = get_free_slot(accepted); diff --git a/samples/shields/lmp90100_evb/rtd/app.overlay b/samples/shields/lmp90100_evb/rtd/app.overlay index 7ea69d39c83f677..27044a27865182c 100644 --- a/samples/shields/lmp90100_evb/rtd/app.overlay +++ b/samples/shields/lmp90100_evb/rtd/app.overlay @@ -1,9 +1,29 @@ /* - * Copyright (c) 2019 Vestas Wind Systems A/S + * Copyright (c) 2019-2024 Vestas Wind Systems A/S * * SPDX-License-Identifier: Apache-2.0 */ +/ { + zephyr,user { + io-channels = <&lmp90100_lmp90100_evb 0>; + }; +}; + &lmp90100_lmp90100_evb { + #address-cells = <1>; + #size-cells = <0>; + rtd-current = <1000>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL1"; + zephyr,acquisition-time = ; + zephyr,resolution = <24>; + zephyr,differential; + zephyr,input-positive = <0>; + zephyr,input-negative = <1>; + }; }; diff --git a/samples/shields/lmp90100_evb/rtd/src/main.c b/samples/shields/lmp90100_evb/rtd/src/main.c index 939f2c331ad51f7..040a1d23509b370 100644 --- a/samples/shields/lmp90100_evb/rtd/src/main.c +++ b/samples/shields/lmp90100_evb/rtd/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Vestas Wind Systems A/S + * Copyright (c) 2019-2024 Vestas Wind Systems A/S * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,11 +17,8 @@ LOG_MODULE_REGISTER(main); /* Nominal RTD (PT100) resistance in ohms */ #define RTD_NOMINAL_RESISTANCE 100 -/* ADC resolution in bits */ -#define ADC_RESOLUTION 24U - /* ADC maximum value (taking sign bit into consideration) */ -#define ADC_MAX BIT_MASK(ADC_RESOLUTION - 1) +#define ADC_MAX(resolution) BIT_MASK(resolution - 1) /* Bottom resistor value in ohms */ #define BOTTOM_RESISTANCE 2000 @@ -42,46 +39,39 @@ static double rtd_temperature(int nom, double resistance) int main(void) { - const struct device *const lmp90100 = DEVICE_DT_GET_ONE(ti_lmp90100); + const struct adc_dt_spec ch_cfg = ADC_DT_SPEC_GET(DT_PATH(zephyr_user)); + double adc_max = ADC_MAX(ch_cfg.resolution); double resistance; int32_t buffer; int err; - const struct adc_channel_cfg ch_cfg = { - .channel_id = 0, - .differential = 1, - .input_positive = 0, - .input_negative = 1, - .reference = ADC_REF_EXTERNAL1, - .gain = ADC_GAIN_1, - .acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_TICKS, 0) - }; - const struct adc_sequence seq = { - .options = NULL, - .channels = BIT(0), + struct adc_sequence seq = { .buffer = &buffer, .buffer_size = sizeof(buffer), - .resolution = ADC_RESOLUTION, - .oversampling = 0, - .calibrate = 0 }; - if (!device_is_ready(lmp90100)) { + if (!adc_is_ready_dt(&ch_cfg)) { LOG_ERR("LMP90100 device not ready"); return 0; } - err = adc_channel_setup(lmp90100, &ch_cfg); - if (err) { + err = adc_channel_setup_dt(&ch_cfg); + if (err != 0) { LOG_ERR("failed to setup ADC channel (err %d)", err); return 0; } + err = adc_sequence_init_dt(&ch_cfg, &seq); + if (err != 0) { + LOG_ERR("failed to initialize ADC sequence (err %d)", err); + return 0; + } + while (true) { - err = adc_read(lmp90100, &seq); - if (err) { + err = adc_read_dt(&ch_cfg, &seq); + if (err != 0) { LOG_ERR("failed to read ADC (err %d)", err); } else { - resistance = (buffer / (double)ADC_MAX) * BOTTOM_RESISTANCE; + resistance = (buffer / adc_max) * BOTTOM_RESISTANCE; printf("R: %.02f ohm\n", resistance); printf("T: %.02f degC\n", rtd_temperature(RTD_NOMINAL_RESISTANCE, diff --git a/samples/subsys/fs/fs_sample/sample.yaml b/samples/subsys/fs/fs_sample/sample.yaml index 375bacf4f8facb9..58c0cf623619dd6 100644 --- a/samples/subsys/fs/fs_sample/sample.yaml +++ b/samples/subsys/fs/fs_sample/sample.yaml @@ -43,6 +43,8 @@ tests: integration_platforms: - frdm_k64f sample.filesystem.ext2: + simulation_exclude: + - renode extra_args: CONF_FILE="prj_ext.conf" platform_allow: hifive_unmatched bl5340_dvk_cpuapp sample.filesystem.fat_fs.stm32h747i_disco_m7_sdmmc: diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/remote/src/main.c b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/src/main.c index 9b288f8a6a1801f..f285f4b6d23c983 100644 --- a/samples/subsys/ipc/ipc_service/multi_endpoint/remote/src/main.c +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/remote/src/main.c @@ -193,7 +193,7 @@ static void ipc1_ept_recv(const void *data, size_t len, void *priv) { ipc1_received_data = *((uint8_t *) data); - k_sem_give(&ipc0B_data_sem); + k_sem_give(&ipc1_data_sem); } static struct ipc_ept_cfg ipc1_ept_cfg = { diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/src/main.c b/samples/subsys/ipc/ipc_service/multi_endpoint/src/main.c index 78d7af05288208a..4ad5659df382325 100644 --- a/samples/subsys/ipc/ipc_service/multi_endpoint/src/main.c +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/src/main.c @@ -190,7 +190,7 @@ static void ipc1_ept_recv(const void *data, size_t len, void *priv) { ipc1_received_data = *((uint8_t *) data); - k_sem_give(&ipc0B_data_sem); + k_sem_give(&ipc1_data_sem); } static struct ipc_ept_cfg ipc1_ept_cfg = { diff --git a/scripts/pylib/twister/twisterlib/coverage.py b/scripts/pylib/twister/twisterlib/coverage.py index 0466215809d8fc2..556f5b359baa443 100644 --- a/scripts/pylib/twister/twisterlib/coverage.py +++ b/scripts/pylib/twister/twisterlib/coverage.py @@ -31,9 +31,9 @@ def __init__(self): self.output_formats = None @staticmethod - def factory(tool): + def factory(tool, jobs=None): if tool == 'lcov': - t = Lcov() + t = Lcov(jobs) elif tool == 'gcovr': t = Gcovr() else: @@ -141,11 +141,12 @@ def generate(self, outdir): class Lcov(CoverageTool): - def __init__(self): + def __init__(self, jobs=None): super().__init__() self.ignores = [] self.output_formats = "lcov,html" self.version = self.get_version() + self.jobs = jobs def get_version(self): try: @@ -168,75 +169,81 @@ def add_ignore_file(self, pattern): def add_ignore_directory(self, pattern): self.ignores.append('*/' + pattern + '/*') - @staticmethod - def run_command(cmd, coveragelog): + @property + def is_lcov_v2(self): + return self.version.startswith("2") + + def run_command(self, cmd, coveragelog): + if self.is_lcov_v2: + # The --ignore-errors source option is added for genhtml as well as + # lcov to avoid it exiting due to + # samples/application_development/external_lib/ + cmd += [ + "--ignore-errors", "inconsistent,inconsistent", + "--ignore-errors", "negative,negative", + "--ignore-errors", "unused,unused", + "--ignore-errors", "empty,empty", + "--ignore-errors", "mismatch,mismatch", + ] + cmd_str = " ".join(cmd) logger.debug(f"Running {cmd_str}...") return subprocess.call(cmd, stdout=coveragelog) - def _generate(self, outdir, coveragelog): - coveragefile = os.path.join(outdir, "coverage.info") - ztestfile = os.path.join(outdir, "ztest.info") - if self.version.startswith("2"): + def run_lcov(self, args, coveragelog): + if self.is_lcov_v2: branch_coverage = "branch_coverage=1" - ignore_errors = [ - "--ignore-errors", "inconsistent,inconsistent", - "--ignore-errors", "negative,negative", - "--ignore-errors", "unused,unused", - "--ignore-errors", "empty,empty", - "--ignore-errors", "mismatch,mismatch" - ] + if self.jobs is None: + # Default: --parallel=0 will autodetect appropriate parallelism + parallel = ["--parallel", "0"] + elif self.jobs == 1: + # Serial execution requested, don't parallelize at all + parallel = [] + else: + parallel = ["--parallel", str(self.jobs)] else: branch_coverage = "lcov_branch_coverage=1" - ignore_errors = [] - - cmd = ["lcov", "--gcov-tool", self.gcov_tool, - "--capture", "--directory", outdir, - "--rc", branch_coverage, - "--output-file", coveragefile] - cmd = cmd + ignore_errors - self.run_command(cmd, coveragelog) - # We want to remove tests/* and tests/ztest/test/* but save tests/ztest - cmd = ["lcov", "--gcov-tool", self.gcov_tool, "--extract", - coveragefile, - os.path.join(self.base_dir, "tests", "ztest", "*"), - "--output-file", ztestfile, - "--rc", branch_coverage] + parallel = [] - cmd = cmd + ignore_errors - self.run_command(cmd, coveragelog) + cmd = [ + "lcov", "--gcov-tool", self.gcov_tool, + "--rc", branch_coverage, + ] + parallel + args + return self.run_command(cmd, coveragelog) + + def _generate(self, outdir, coveragelog): + coveragefile = os.path.join(outdir, "coverage.info") + ztestfile = os.path.join(outdir, "ztest.info") + + cmd = ["--capture", "--directory", outdir, "--output-file", coveragefile] + self.run_lcov(cmd, coveragelog) + + # We want to remove tests/* and tests/ztest/test/* but save tests/ztest + cmd = ["--extract", coveragefile, + os.path.join(self.base_dir, "tests", "ztest", "*"), + "--output-file", ztestfile] + self.run_lcov(cmd, coveragelog) if os.path.exists(ztestfile) and os.path.getsize(ztestfile) > 0: - cmd = ["lcov", "--gcov-tool", self.gcov_tool, "--remove", - ztestfile, - os.path.join(self.base_dir, "tests/ztest/test/*"), - "--output-file", ztestfile, - "--rc", branch_coverage] - cmd = cmd + ignore_errors - self.run_command(cmd, coveragelog) + cmd = ["--remove", ztestfile, + os.path.join(self.base_dir, "tests/ztest/test/*"), + "--output-file", ztestfile] + self.run_lcov(cmd, coveragelog) files = [coveragefile, ztestfile] else: files = [coveragefile] for i in self.ignores: - cmd = ["lcov", "--gcov-tool", self.gcov_tool, "--remove", - coveragefile, i, - "--output-file", coveragefile, - "--rc", branch_coverage] - cmd = cmd + ignore_errors - self.run_command(cmd, coveragelog) + cmd = ["--remove", coveragefile, i, "--output-file", coveragefile] + self.run_lcov(cmd, coveragelog) if 'html' not in self.output_formats.split(','): return 0 - # The --ignore-errors source option is added to avoid it exiting due to - # samples/application_development/external_lib/ cmd = ["genhtml", "--legend", "--branch-coverage", - "--prefix", self.base_dir, - "-output-directory", - os.path.join(outdir, "coverage")] + files - cmd = cmd + ignore_errors + "--prefix", self.base_dir, + "-output-directory", os.path.join(outdir, "coverage")] + files return self.run_command(cmd, coveragelog) @@ -367,7 +374,7 @@ def run_coverage(testplan, options): logger.info("Generating coverage files...") logger.info(f"Using gcov tool: {gcov_tool}") - coverage_tool = CoverageTool.factory(options.coverage_tool) + coverage_tool = CoverageTool.factory(options.coverage_tool, jobs=options.jobs) coverage_tool.gcov_tool = gcov_tool coverage_tool.base_dir = os.path.abspath(options.coverage_basedir) # Apply output format default diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index da902cc5ef6bc31..3a13b819649e907 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -363,7 +363,7 @@ def __init__(self, instance, type_str): def get_test_timeout(self): timeout = super().get_test_timeout() - if self.options.coverage: + if self.options.enable_coverage: # wait more for gcov data to be dumped on console timeout += 120 return timeout @@ -371,7 +371,7 @@ def get_test_timeout(self): def monitor_serial(self, ser, halt_event, harness): log_out_fp = open(self.log, "wb") - if self.options.coverage: + if self.options.enable_coverage: # Set capture_coverage to True to indicate that right after # test results we should get coverage data, otherwise we exit # from the test. diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index c1d0b6fd23cd017..bfdcb107ec8f2ff 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -12,6 +12,7 @@ import logging import threading import time +import shutil from twisterlib.error import ConfigurationError from twisterlib.environment import ZEPHYR_BASE, PYTEST_PLUGIN_INSTALLED @@ -83,6 +84,8 @@ def configure(self, instance): if self.record: self.record_pattern = re.compile(self.record.get("regex", "")) + def build(self): + pass def get_testcase_name(self): """ @@ -651,13 +654,51 @@ class Ztest(Test): pass +class Bsim(Harness): + + def build(self): + """ + Copying the application executable to BabbleSim's bin directory enables + running multidevice bsim tests after twister has built them. + """ + + if self.instance is None: + return + + original_exe_path: str = os.path.join(self.instance.build_dir, 'zephyr', 'zephyr.exe') + if not os.path.exists(original_exe_path): + logger.warning('Cannot copy bsim exe - cannot find original executable.') + return + + bsim_out_path: str = os.getenv('BSIM_OUT_PATH', '') + if not bsim_out_path: + logger.warning('Cannot copy bsim exe - BSIM_OUT_PATH not provided.') + return + + new_exe_name: str = self.instance.testsuite.harness_config.get('bsim_exe_name', '') + if new_exe_name: + new_exe_name = f'bs_{self.instance.platform.name}_{new_exe_name}' + else: + new_exe_name = self.instance.name + new_exe_name = new_exe_name.replace(os.path.sep, '_').replace('.', '_') + new_exe_name = f'bs_{new_exe_name}' + + new_exe_path: str = os.path.join(bsim_out_path, 'bin', new_exe_name) + logger.debug(f'Copying executable from {original_exe_path} to {new_exe_path}') + shutil.copy(original_exe_path, new_exe_path) + + class HarnessImporter: @staticmethod def get_harness(harness_name): thismodule = sys.modules[__name__] - if harness_name: - harness_class = getattr(thismodule, harness_name) - else: - harness_class = getattr(thismodule, 'Test') - return harness_class() + try: + if harness_name: + harness_class = getattr(thismodule, harness_name) + else: + harness_class = getattr(thismodule, 'Test') + return harness_class() + except AttributeError as e: + logger.debug(f"harness {harness_name} not implemented: {e}") + return None diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 2d948336f509d6c..9ef53b386c9c7da 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -1052,7 +1052,18 @@ def cmake(self, filter_stages=[]): return self.run_cmake(args,filter_stages) def build(self): - return self.run_build(['--build', self.build_dir]) + harness = HarnessImporter.get_harness(self.instance.testsuite.harness.capitalize()) + build_result = self.run_build(['--build', self.build_dir]) + try: + if harness: + harness.instance = self.instance + harness.build() + except ConfigurationError as error: + self.instance.status = "error" + self.instance.reason = str(error) + logger.error(self.instance.reason) + return + return build_result def run(self): diff --git a/scripts/schemas/twister/testsuite-schema.yaml b/scripts/schemas/twister/testsuite-schema.yaml index 31aacc76edf060b..cdec09e536c45b5 100644 --- a/scripts/schemas/twister/testsuite-schema.yaml +++ b/scripts/schemas/twister/testsuite-schema.yaml @@ -123,6 +123,9 @@ mapping: "regex": type: str required: true + "bsim_exe_name": + type: str + required: false "min_ram": type: int required: false @@ -346,6 +349,9 @@ mapping: "regex": type: str required: true + "bsim_exe_name": + type: str + required: false "min_ram": type: int required: false diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py index 931df46e674a3a9..d2e4b367a79471e 100644 --- a/scripts/tests/twister/test_handlers.py +++ b/scripts/tests/twister/test_handlers.py @@ -740,7 +740,7 @@ def test_devicehandler_monitor_serial( type(harness).state=mock.PropertyMock(side_effect=state_iter) handler = DeviceHandler(mocked_instance, 'build') - handler.options = mock.Mock(coverage=not end_by_state) + handler.options = mock.Mock(enable_coverage=not end_by_state) with mock.patch('builtins.open', mock.mock_open(read_data='')): handler.monitor_serial(ser, halt_event, harness) diff --git a/scripts/tests/twister/test_harness.py b/scripts/tests/twister/test_harness.py index 247a9426f7bb756..f0697efc43dbd15 100644 --- a/scripts/tests/twister/test_harness.py +++ b/scripts/tests/twister/test_harness.py @@ -14,7 +14,7 @@ ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister")) -from twisterlib.harness import Gtest +from twisterlib.harness import Gtest, Bsim from twisterlib.testinstance import TestInstance GTEST_START_STATE = " RUN " @@ -35,7 +35,7 @@ def process_logs(harness, logs): @pytest.fixture -def gtest(): +def gtest(tmp_path): mock_platform = mock.Mock() mock_platform.name = "mock_platform" mock_testsuite = mock.Mock() @@ -44,8 +44,10 @@ def gtest(): mock_testsuite.id = "id" mock_testsuite.testcases = [] mock_testsuite.harness_config = {} + outdir = tmp_path / 'gtest_out' + outdir.mkdir() - instance = TestInstance(testsuite=mock_testsuite, platform=mock_platform, outdir="") + instance = TestInstance(testsuite=mock_testsuite, platform=mock_platform, outdir=outdir) harness = Gtest() harness.configure(instance) @@ -250,3 +252,30 @@ def test_gtest_repeated_run(gtest): ), ], ) + + +def test_bsim_build(monkeypatch, tmp_path): + mocked_instance = mock.Mock() + build_dir = tmp_path / 'build_dir' + os.makedirs(build_dir) + mocked_instance.build_dir = str(build_dir) + mocked_instance.name = 'platform_name/test/dummy.test' + mocked_instance.testsuite.harness_config = {} + + harness = Bsim() + harness.instance = mocked_instance + + monkeypatch.setenv('BSIM_OUT_PATH', str(tmp_path)) + os.makedirs(os.path.join(tmp_path, 'bin'), exist_ok=True) + zephyr_exe_path = os.path.join(build_dir, 'zephyr', 'zephyr.exe') + os.makedirs(os.path.dirname(zephyr_exe_path), exist_ok=True) + with open(zephyr_exe_path, 'w') as file: + file.write('TEST_EXE') + + harness.build() + + new_exe_path = os.path.join(tmp_path, 'bin', 'bs_platform_name_test_dummy_test') + assert os.path.exists(new_exe_path) + with open(new_exe_path, 'r') as file: + exe_content = file.read() + assert 'TEST_EXE' in exe_content diff --git a/scripts/tests/twister/test_platform.py b/scripts/tests/twister/test_platform.py new file mode 100644 index 000000000000000..c40a10a9b781099 --- /dev/null +++ b/scripts/tests/twister/test_platform.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +''' +This test file contains tests for platform.py module of twister +''' +import sys +import os +import mock +import pytest + +ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") +sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister")) + +from twisterlib.platform import Platform + + +TESTDATA_1 = [ + ( +"""\ +identifier: dummy empty +arch: arch0 +""", + { + 'name': 'dummy empty', + 'arch': 'arch0', + 'twister': True, + 'ram': 128, + 'timeout_multiplier': 1.0, + 'ignore_tags': [], + 'only_tags': [], + 'default': False, + 'binaries': [], + 'flash': 512, + 'supported': set(), + 'vendor': '', + 'tier': -1, + 'type': 'na', + 'simulation': 'na', + 'simulation_exec': None, + 'supported_toolchains': [], + 'env': [], + 'env_satisfied': True + }, + '' + ), + ( +"""\ +identifier: dummy full +arch: riscv32 +twister: true +ram: 1024 +testing: + timeout_multiplier: 2.0 + ignore_tags: + - tag1 + - tag2 + only_tags: + - tag3 + default: true + binaries: + - dummy.exe + - dummy.bin +flash: 4096 +supported: + - ble + - netif:openthread + - gpio +vendor: vendor1 +tier: 1 +type: unit +simulation: nsim +simulation_exec: nsimdrv +toolchain: + - zephyr + - llvm +env: + - dummynonexistentvar +""", + { + 'name': 'dummy full', + 'arch': 'riscv32', + 'twister': True, + 'ram': 1024, + 'timeout_multiplier': 2.0, + 'ignore_tags': ['tag1', 'tag2'], + 'only_tags': ['tag3'], + 'default': True, + 'binaries': ['dummy.exe', 'dummy.bin'], + 'flash': 4096, + 'supported': set(['ble', 'netif', 'openthread', 'gpio']), + 'vendor': 'vendor1', + 'tier': 1, + 'type': 'unit', + 'simulation': 'nsim', + 'simulation_exec': 'nsimdrv', + 'supported_toolchains': ['zephyr', 'llvm', 'cross-compile', 'xtools'], + 'env': ['dummynonexistentvar'], + 'env_satisfied': False + }, + '' + ), +] + +@pytest.mark.parametrize( + 'platform_text, expected_data, expected_repr', + TESTDATA_1, + ids=['almost empty specification', 'full specification'] +) +def test_platform_load(platform_text, expected_data, expected_repr): + platform = Platform() + + with mock.patch('builtins.open', mock.mock_open(read_data=platform_text)): + platform.load('dummy.yaml') + + for k, v in expected_data.items(): + if not hasattr(platform, k): + assert False, f'No key {k} in platform {platform}' + att = getattr(platform, k) + if isinstance(v, list) and not isinstance(att, list): + assert False, f'Value mismatch in key {k} in platform {platform}' + if isinstance(v, list): + assert sorted(att) == sorted(v) + else: + assert att == v + + assert platform.__repr__() == expected_repr diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index 8b98e79a5a3c8a9..fcf6ccd2a0193e2 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -2071,6 +2071,7 @@ def test_projectbuilder_cmake(): def test_projectbuilder_build(mocked_jobserver): instance_mock = mock.Mock() + instance_mock.testsuite.harness = 'test' env_mock = mock.Mock() pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver) diff --git a/scripts/tests/twister/test_testinstance.py b/scripts/tests/twister/test_testinstance.py index 73a3c8f7dfbffdd..52c51b2b278e90d 100644 --- a/scripts/tests/twister/test_testinstance.py +++ b/scripts/tests/twister/test_testinstance.py @@ -7,21 +7,23 @@ Tests for testinstance class """ +from contextlib import nullcontext import os import sys import pytest - -from unittest import mock +import mock ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister")) + from twisterlib.testinstance import TestInstance from twisterlib.error import BuildError from twisterlib.runner import TwisterRunner +from twisterlib.handlers import QEMUHandler from expr_parser import reserved -TESTDATA_1 = [ +TESTDATA_PART_1 = [ (False, False, "console", "na", "qemu", False, [], (False, True)), (False, False, "console", "native", "qemu", False, [], (False, True)), (True, False, "console", "native", "nsim", False, [], (True, False)), @@ -30,14 +32,30 @@ (False, False, "sensor", "na", "", False, [], (True, False)), (False, True, "sensor", "native", "", True, [], (True, False)), ] -@pytest.mark.parametrize("build_only, slow, harness, platform_type, platform_sim, device_testing,fixture, expected", TESTDATA_1) -def test_check_build_or_run(class_testplan, all_testsuites_dict, platforms_list, build_only, slow, harness, platform_type, platform_sim, device_testing, fixture, expected): +@pytest.mark.parametrize( + "build_only, slow, harness, platform_type, platform_sim, device_testing,fixture, expected", + TESTDATA_PART_1 +) +def test_check_build_or_run( + class_testplan, + all_testsuites_dict, + platforms_list, + build_only, + slow, + harness, + platform_type, + platform_sim, + device_testing, + fixture, + expected +): """" Test to check the conditions for build_only and run scenarios Scenario 1: Test when different parameters are passed, build_only and run are set correctly Scenario 2: Test if build_only is enabled when the OS is Windows""" class_testplan.testsuites = all_testsuites_dict - testsuite = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1') + testsuite = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/tests/' + 'test_a/test_a.check_1') print(testsuite) class_testplan.platforms = platforms_list @@ -57,27 +75,52 @@ def test_check_build_or_run(class_testplan, all_testsuites_dict, platforms_list, run = testinstance.check_runnable() assert not run -TESTDATA_2 = [ - (True, True, True, ["demo_board_2"], "native", None, '\nCONFIG_COVERAGE=y\nCONFIG_COVERAGE_DUMP=y\nCONFIG_ASAN=y\nCONFIG_UBSAN=y'), - (True, False, True, ["demo_board_2"], "native", None, '\nCONFIG_COVERAGE=y\nCONFIG_COVERAGE_DUMP=y\nCONFIG_ASAN=y'), - (False, False, True, ["demo_board_2"], 'native', None, '\nCONFIG_COVERAGE=y\nCONFIG_COVERAGE_DUMP=y'), - (True, False, True, ["demo_board_2"], 'mcu', None, '\nCONFIG_COVERAGE=y\nCONFIG_COVERAGE_DUMP=y'), +TESTDATA_PART_2 = [ + (True, True, True, ["demo_board_2"], "native", + None, '\nCONFIG_COVERAGE=y\nCONFIG_COVERAGE_DUMP=y\nCONFIG_ASAN=y\nCONFIG_UBSAN=y'), + (True, False, True, ["demo_board_2"], "native", + None, '\nCONFIG_COVERAGE=y\nCONFIG_COVERAGE_DUMP=y\nCONFIG_ASAN=y'), + (False, False, True, ["demo_board_2"], 'native', + None, '\nCONFIG_COVERAGE=y\nCONFIG_COVERAGE_DUMP=y'), + (True, False, True, ["demo_board_2"], 'mcu', + None, '\nCONFIG_COVERAGE=y\nCONFIG_COVERAGE_DUMP=y'), (False, False, False, ["demo_board_2"], 'native', None, ''), (False, False, True, ['demo_board_1'], 'native', None, ''), (True, False, False, ["demo_board_2"], 'native', None, '\nCONFIG_ASAN=y'), (False, True, False, ["demo_board_2"], 'native', None, '\nCONFIG_UBSAN=y'), - (False, False, False, ["demo_board_2"], 'native', ["CONFIG_LOG=y"], 'CONFIG_LOG=y'), - (False, False, False, ["demo_board_2"], 'native', ["arch:x86_demo:CONFIG_LOG=y"], 'CONFIG_LOG=y'), - (False, False, False, ["demo_board_2"], 'native', ["arch:arm_demo:CONFIG_LOG=y"], ''), - (False, False, False, ["demo_board_2"], 'native', ["platform:demo_board_2:CONFIG_LOG=y"], 'CONFIG_LOG=y'), - (False, False, False, ["demo_board_2"], 'native', ["platform:demo_board_1:CONFIG_LOG=y"], ''), + (False, False, False, ["demo_board_2"], 'native', + ["CONFIG_LOG=y"], 'CONFIG_LOG=y'), + (False, False, False, ["demo_board_2"], 'native', + ["arch:x86_demo:CONFIG_LOG=y"], 'CONFIG_LOG=y'), + (False, False, False, ["demo_board_2"], 'native', + ["arch:arm_demo:CONFIG_LOG=y"], ''), + (False, False, False, ["demo_board_2"], 'native', + ["platform:demo_board_2:CONFIG_LOG=y"], 'CONFIG_LOG=y'), + (False, False, False, ["demo_board_2"], 'native', + ["platform:demo_board_1:CONFIG_LOG=y"], ''), ] -@pytest.mark.parametrize("enable_asan, enable_ubsan, enable_coverage, coverage_platform, platform_type, extra_configs, expected_content", TESTDATA_2) -def test_create_overlay(class_testplan, all_testsuites_dict, platforms_list, enable_asan, enable_ubsan, enable_coverage, coverage_platform, platform_type, extra_configs, expected_content): +@pytest.mark.parametrize( + 'enable_asan, enable_ubsan, enable_coverage, coverage_platform, platform_type,' + ' extra_configs, expected_content', + TESTDATA_PART_2 +) +def test_create_overlay( + class_testplan, + all_testsuites_dict, + platforms_list, + enable_asan, + enable_ubsan, + enable_coverage, + coverage_platform, + platform_type, + extra_configs, + expected_content +): """Test correct content is written to testcase_extra.conf based on if conditions.""" class_testplan.testsuites = all_testsuites_dict - testcase = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/samples/test_app/sample_test.app') + testcase = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/samples/' + 'test_app/sample_test.app') if extra_configs: testcase.extra_configs = extra_configs @@ -92,7 +135,8 @@ def test_create_overlay(class_testplan, all_testsuites_dict, platforms_list, ena def test_calculate_sizes(class_testplan, all_testsuites_dict, platforms_list): """ Test Calculate sizes method for zephyr elf""" class_testplan.testsuites = all_testsuites_dict - testcase = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/samples/test_app/sample_test.app') + testcase = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/samples/' + 'test_app/sample_test.app') class_testplan.platforms = platforms_list platform = class_testplan.get_platform("demo_board_2") testinstance = TestInstance(testcase, platform, class_testplan.env.outdir) @@ -100,15 +144,452 @@ def test_calculate_sizes(class_testplan, all_testsuites_dict, platforms_list): with pytest.raises(BuildError): assert testinstance.calculate_sizes() == "Missing/multiple output ELF binary" -TESTDATA_3 = [ - ('CONFIG_ARCH_HAS_THREAD_LOCAL_STORAGE and CONFIG_TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE and not (CONFIG_TOOLCHAIN_ARCMWDT_SUPPORTS_THREAD_LOCAL_STORAGE and CONFIG_USERSPACE)', ['kconfig']), - ('(dt_compat_enabled("st,stm32-flash-controller") or dt_compat_enabled("st,stm32h7-flash-controller")) and dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions")', ['dts']), - ('((CONFIG_FLASH_HAS_DRIVER_ENABLED and not CONFIG_TRUSTED_EXECUTION_NONSECURE) and dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions")) or (CONFIG_FLASH_HAS_DRIVER_ENABLED and CONFIG_TRUSTED_EXECUTION_NONSECURE and dt_label_with_parent_compat_enabled("slot1_ns_partition", "fixed-partitions"))', ['dts', 'kconfig']), - ('((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and CONFIG_CPU_HAS_FPU and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX', ['full']) +TESTDATA_PART_3 = [ + ( + 'CONFIG_ARCH_HAS_THREAD_LOCAL_STORAGE and' \ + ' CONFIG_TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE and' \ + ' not (CONFIG_TOOLCHAIN_ARCMWDT_SUPPORTS_THREAD_LOCAL_STORAGE and CONFIG_USERSPACE)', + ['kconfig'] + ), + ( + '(dt_compat_enabled("st,stm32-flash-controller") or' \ + ' dt_compat_enabled("st,stm32h7-flash-controller")) and' \ + ' dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions")', + ['dts'] + ), + ( + '((CONFIG_FLASH_HAS_DRIVER_ENABLED and not CONFIG_TRUSTED_EXECUTION_NONSECURE) and' \ + ' dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions")) or' \ + ' (CONFIG_FLASH_HAS_DRIVER_ENABLED and CONFIG_TRUSTED_EXECUTION_NONSECURE and' \ + ' dt_label_with_parent_compat_enabled("slot1_ns_partition", "fixed-partitions"))', + ['dts', 'kconfig'] + ), + ( + '((CONFIG_CPU_AARCH32_CORTEX_R or CONFIG_CPU_CORTEX_M) and' \ + ' CONFIG_CPU_HAS_FPU and TOOLCHAIN_HAS_NEWLIB == 1) or CONFIG_ARCH_POSIX', + ['full'] + ) ] -@pytest.mark.parametrize("filter_expr, expected_stages", TESTDATA_3) +@pytest.mark.parametrize("filter_expr, expected_stages", TESTDATA_PART_3) def test_which_filter_stages(filter_expr, expected_stages): logic_keys = reserved.keys() stages = TwisterRunner.get_cmake_filter_stages(filter_expr, logic_keys) assert sorted(stages) == sorted(expected_stages) + + +@pytest.fixture(name='testinstance') +def sample_testinstance(all_testsuites_dict, class_testplan, platforms_list, request): + testsuite_path = 'scripts/tests/twister/test_data/testsuites' + if request.param['testsuite_kind'] == 'sample': + testsuite_path += '/samples/test_app/sample_test.app' + elif request.param['testsuite_kind'] == 'tests': + testsuite_path += '/tests/test_a/test_a.check_1' + + class_testplan.testsuites = all_testsuites_dict + testsuite = class_testplan.testsuites.get(testsuite_path) + class_testplan.platforms = platforms_list + platform = class_testplan.get_platform(request.param.get('board_name', 'demo_board_2')) + + testinstance = TestInstance(testsuite, platform, class_testplan.env.outdir) + return testinstance + + +TESTDATA_1 = [ + (False), + (True), +] + +@pytest.mark.parametrize('detailed_test_id', TESTDATA_1) +def test_testinstance_init(all_testsuites_dict, class_testplan, platforms_list, detailed_test_id): + testsuite_path = 'scripts/tests/twister/test_data/testsuites/samples/test_app/sample_test.app' + class_testplan.testsuites = all_testsuites_dict + testsuite = class_testplan.testsuites.get(testsuite_path) + testsuite.detailed_test_id = detailed_test_id + class_testplan.platforms = platforms_list + platform = class_testplan.get_platform("demo_board_2") + + testinstance = TestInstance(testsuite, platform, class_testplan.env.outdir) + + if detailed_test_id: + assert testinstance.build_dir == os.path.join(class_testplan.env.outdir, platform.name, testsuite_path) + else: + assert testinstance.build_dir == os.path.join(class_testplan.env.outdir, platform.name, testsuite.source_dir_rel, testsuite.name) + + +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'sample'}], indirect=True) +def test_testinstance_add_filter(testinstance): + reason = 'dummy reason' + filter_type = 'dummy type' + + testinstance.add_filter(reason, filter_type) + + assert {'type': filter_type, 'reason': reason} in testinstance.filters + assert testinstance.status == 'filtered' + assert testinstance.reason == reason + assert testinstance.filter_type == filter_type + + +def test_testinstance_init_cases(all_testsuites_dict, class_testplan, platforms_list): + testsuite_path = 'scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1' + class_testplan.testsuites = all_testsuites_dict + testsuite = class_testplan.testsuites.get(testsuite_path) + class_testplan.platforms = platforms_list + platform = class_testplan.get_platform("demo_board_2") + + testinstance = TestInstance(testsuite, platform, class_testplan.env.outdir) + + testinstance.init_cases() + + assert all( + [ + any( + [ + tcc.name == tc.name and tcc.freeform == tc.freeform \ + for tcc in testinstance.testsuite.testcases + ] + ) for tc in testsuite.testcases + ] + ) + + +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'sample'}], indirect=True) +def test_testinstance_get_run_id(testinstance): + res = testinstance._get_run_id() + + assert isinstance(res, str) + + +TESTDATA_2 = [ + ('another reason', 'another reason'), + (None, 'dummy reason'), +] + +@pytest.mark.parametrize('reason, expected_reason', TESTDATA_2) +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_add_missing_case_status(testinstance, reason, expected_reason): + testinstance.reason = 'dummy reason' + + status = 'passed' + + assert len(testinstance.testcases) > 1, 'Selected testsuite does not have enough testcases.' + + testinstance.testcases[0].status = 'started' + testinstance.testcases[-1].status = None + + testinstance.add_missing_case_status(status, reason) + + assert testinstance.testcases[0].status == 'failed' + assert testinstance.testcases[-1].status == 'passed' + assert testinstance.testcases[-1].reason == expected_reason + + +def test_testinstance_dunders(all_testsuites_dict, class_testplan, platforms_list): + testsuite_path = 'scripts/tests/twister/test_data/testsuites/samples/test_app/sample_test.app' + class_testplan.testsuites = all_testsuites_dict + testsuite = class_testplan.testsuites.get(testsuite_path) + class_testplan.platforms = platforms_list + platform = class_testplan.get_platform("demo_board_2") + + testinstance = TestInstance(testsuite, platform, class_testplan.env.outdir) + testinstance_copy = TestInstance(testsuite, platform, class_testplan.env.outdir) + + d = testinstance.__getstate__() + + d['name'] = 'dummy name' + testinstance_copy.__setstate__(d) + + d['name'] = 'another name' + testinstance.__setstate__(d) + + assert testinstance < testinstance_copy + + testinstance_copy.__setstate__(d) + + assert not testinstance < testinstance_copy + assert not testinstance_copy < testinstance + + assert testinstance.__repr__() == f'' + + +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_set_case_status_by_name(testinstance): + name = 'test_a.check_1.2a' + status = 'dummy status' + reason = 'dummy reason' + + tc = testinstance.set_case_status_by_name(name, status, reason) + + assert tc.name == name + assert tc.status == status + assert tc.reason == reason + + tc = testinstance.set_case_status_by_name(name, status, None) + + assert tc.reason == reason + + +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_add_testcase(testinstance): + name = 'test_a.check_1.3a' + freeform = True + + tc = testinstance.add_testcase(name, freeform) + + assert tc in testinstance.testcases + + +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_get_case_by_name(testinstance): + name = 'test_a.check_1.2a' + + tc = testinstance.get_case_by_name(name) + + assert tc.name == name + + name = 'test_a.check_1.3a' + + tc = testinstance.get_case_by_name(name) + + assert tc is None + + +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_get_case_or_create(caplog, testinstance): + name = 'test_a.check_1.2a' + + tc = testinstance.get_case_or_create(name) + + assert tc.name == name + + name = 'test_a.check_1.3a' + + tc = testinstance.get_case_or_create(name) + + assert tc.name == name + assert 'Could not find a matching testcase for test_a.check_1.3a' in caplog.text + + +TESTDATA_3 = [ + (None, 'nonexistent harness', False), + ('nonexistent fixture', 'console', False), + (None, 'console', True), + ('dummy fixture', 'console', True), +] + +@pytest.mark.parametrize( + 'fixture, harness, expected_can_run', + TESTDATA_3, + ids=['improper harness', 'fixture not in list', 'no fixture specified', 'fixture in list'] +) +def test_testinstance_testsuite_runnable( + all_testsuites_dict, + class_testplan, + fixture, + harness, + expected_can_run +): + testsuite_path = 'scripts/tests/twister/test_data/testsuites/samples/test_app/sample_test.app' + class_testplan.testsuites = all_testsuites_dict + testsuite = class_testplan.testsuites.get(testsuite_path) + + testsuite.harness = harness + testsuite.harness_config['fixture'] = fixture + + fixtures = ['dummy fixture'] + + can_run = TestInstance.testsuite_runnable(testsuite, fixtures)\ + + assert can_run == expected_can_run + + +TESTDATA_4 = [ + (True, mock.ANY, mock.ANY, mock.ANY, None, [], False), + (False, True, mock.ANY, mock.ANY, 'device', [], True), + (False, False, 'qemu', mock.ANY, 'qemu', ['QEMU_PIPE=1'], True), + (False, False, 'dummy sim', mock.ANY, 'dummy sim', [], True), + (False, False, 'na', 'unit', 'unit', ['COVERAGE=1'], True), + (False, False, 'na', 'dummy type', '', [], False), +] + +@pytest.mark.parametrize( + 'preexisting_handler, device_testing, platform_sim, testsuite_type,' \ + ' expected_handler_type, expected_handler_args, expected_handler_ready', + TESTDATA_4, + ids=['preexisting handler', 'device testing', 'qemu simulation', + 'non-qemu simulation with exec', 'unit teting', 'no handler'] +) +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_setup_handler( + testinstance, + preexisting_handler, + device_testing, + platform_sim, + testsuite_type, + expected_handler_type, + expected_handler_args, + expected_handler_ready +): + testinstance.handler = mock.Mock() if preexisting_handler else None + testinstance.platform.simulation = platform_sim + testinstance.platform.simulation_exec = 'dummy exec' + testinstance.testsuite.type = testsuite_type + env = mock.Mock( + options=mock.Mock( + device_testing=device_testing, + enable_coverage=True + ) + ) + + with mock.patch.object(QEMUHandler, 'get_fifo', return_value=1), \ + mock.patch('shutil.which', return_value=True): + testinstance.setup_handler(env) + + if expected_handler_type: + assert testinstance.handler.type_str == expected_handler_type + assert testinstance.handler.ready == expected_handler_ready + assert all([arg in testinstance.handler.args for arg in expected_handler_args]) + + +TESTDATA_5 = [ + ('nt', 'renode', mock.ANY, mock.ANY, + mock.ANY, mock.ANY, mock.ANY, + mock.ANY, mock.ANY, mock.ANY, mock.ANY, False), + ('linux', mock.ANY, mock.ANY, mock.ANY, + True, mock.ANY, mock.ANY, + mock.ANY, mock.ANY, mock.ANY, mock.ANY, False), + ('linux', mock.ANY, mock.ANY, mock.ANY, + False, True, mock.ANY, + False, mock.ANY, mock.ANY, mock.ANY, False), + ('linux', 'qemu', mock.ANY, mock.ANY, + False, mock.ANY, 'pytest', + mock.ANY, 'not runnable', mock.ANY, None, True), + ('linux', 'renode', 'renode', True, + False, mock.ANY, 'console', + mock.ANY, 'not runnable', [], None, True), + ('linux', 'renode', 'renode', False, + False, mock.ANY, 'not pytest', + mock.ANY, 'not runnable', mock.ANY, None, False), + ('linux', 'qemu', mock.ANY, mock.ANY, + False, mock.ANY, 'console', + mock.ANY, 'not runnable', ['?'], mock.Mock(duts=[mock.Mock(platform='demo_board_2', fixtures=[])]), True), +] + +@pytest.mark.parametrize( + 'os_name, platform_sim, platform_sim_exec, exec_exists,' \ + ' testsuite_build_only, testsuite_slow, testsuite_harness,' \ + ' enable_slow, filter, fixtures, hardware_map, expected', + TESTDATA_5, + ids=['windows', 'build only', 'skip slow', 'pytest harness', 'sim', 'no sim', 'hardware map'] +) +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_check_runnable( + testinstance, + os_name, + platform_sim, + platform_sim_exec, + exec_exists, + testsuite_build_only, + testsuite_slow, + testsuite_harness, + enable_slow, + filter, + fixtures, + hardware_map, + expected +): + testinstance.platform.simulation = platform_sim + testinstance.platform.simulation_exec = platform_sim_exec + testinstance.testsuite.build_only = testsuite_build_only + testinstance.testsuite.slow = testsuite_slow + testinstance.testsuite.harness = testsuite_harness + + with mock.patch('os.name', os_name), \ + mock.patch('shutil.which', return_value=exec_exists): + res = testinstance.check_runnable(enable_slow, filter, fixtures, hardware_map) + + assert res == expected + + +TESTDATA_6 = [ + (True, 'build.log'), + (False, ''), +] + +@pytest.mark.parametrize('from_buildlog, expected_buildlog_filepath', TESTDATA_6) +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_calculate_sizes(testinstance, from_buildlog, expected_buildlog_filepath): + expected_elf_filepath = 'dummy.elf' + expected_extra_sections = [] + expected_warning = True + testinstance.get_elf_file = mock.Mock(return_value='dummy.elf') + testinstance.get_buildlog_file = mock.Mock(return_value='build.log') + + sc_mock = mock.Mock() + mock_sc = mock.Mock(return_value=sc_mock) + + with mock.patch('twisterlib.testinstance.SizeCalculator', mock_sc): + res = testinstance.calculate_sizes(from_buildlog, expected_warning) + + assert res == sc_mock + mock_sc.assert_called_once_with( + elf_filename=expected_elf_filepath, + extra_sections=expected_extra_sections, + buildlog_filepath=expected_buildlog_filepath, + generate_warning=expected_warning + ) + + +TESTDATA_7 = [ + (True, None), + (False, BuildError), +] + +@pytest.mark.parametrize('sysbuild, expected_error', TESTDATA_7) +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_get_elf_file(caplog, tmp_path, testinstance, sysbuild, expected_error): + sysbuild_dir = tmp_path / 'sysbuild' + sysbuild_dir.mkdir() + zephyr_dir = sysbuild_dir / 'zephyr' + zephyr_dir.mkdir() + sysbuild_elf = zephyr_dir / 'dummy.elf' + sysbuild_elf.write_bytes(b'0') + sysbuild_elf2 = zephyr_dir / 'dummy2.elf' + sysbuild_elf2.write_bytes(b'0') + + testinstance.testsuite.sysbuild = sysbuild + testinstance.domains = mock.Mock( + get_default_domain=mock.Mock( + return_value=mock.Mock( + build_dir=sysbuild_dir + ) + ) + ) + + with pytest.raises(expected_error) if expected_error else nullcontext(): + testinstance.get_elf_file() + + if expected_error is None: + assert 'multiple ELF files detected: ' in caplog.text + + +TESTDATA_8 = [ + (True, None), + (False, BuildError), +] + +@pytest.mark.parametrize('create_build_log, expected_error', TESTDATA_8) +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'tests'}], indirect=True) +def test_testinstance_get_buildlog_file(tmp_path, testinstance, create_build_log, expected_error): + if create_build_log: + build_dir = tmp_path / 'build' + build_dir.mkdir() + build_log = build_dir / 'build.log' + build_log.write_text('') + testinstance.build_dir = build_dir + + with pytest.raises(expected_error) if expected_error else nullcontext(): + res = testinstance.get_buildlog_file() + + if expected_error is None: + assert res == str(build_log) diff --git a/scripts/tests/twister/test_testplan.py b/scripts/tests/twister/test_testplan.py new file mode 100644 index 000000000000000..473085467d2ce86 --- /dev/null +++ b/scripts/tests/twister/test_testplan.py @@ -0,0 +1,1776 @@ +#!/usr/bin/env python3 +# Copyright (c) 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +''' +This test file contains testsuites for testsuite.py module of twister +''' +import sys +import os +import mock +import pytest + +from contextlib import nullcontext + +ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") +sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister")) + +from twisterlib.testplan import TestPlan, change_skip_to_error_if_integration +from twisterlib.testinstance import TestInstance +from twisterlib.testsuite import TestSuite +from twisterlib.platform import Platform +from twisterlib.quarantine import Quarantine +from twisterlib.error import TwisterRuntimeError + + +def test_testplan_add_testsuites_short(class_testplan): + """ Testing add_testcase function of Testsuite class in twister """ + # Test 1: Check the list of testsuites after calling add testsuites function is as expected + class_testplan.SAMPLE_FILENAME = 'test_sample_app.yaml' + class_testplan.TESTSUITE_FILENAME = 'test_data.yaml' + class_testplan.add_testsuites() + + tests_rel_dir = 'scripts/tests/twister/test_data/testsuites/tests/' + expected_testsuites = ['test_b.check_1', + 'test_b.check_2', + 'test_c.check_1', + 'test_c.check_2', + 'test_a.check_1', + 'test_a.check_2', + 'test_d.check_1', + 'test_e.check_1', + 'sample_test.app', + 'test_config.main'] + testsuite_list = [] + for key in sorted(class_testplan.testsuites.keys()): + testsuite_list.append(os.path.basename(os.path.normpath(key))) + assert sorted(testsuite_list) == sorted(expected_testsuites) + + # Test 2 : Assert Testcase name is expected & all testsuites values are testcase class objects + suite = class_testplan.testsuites.get(tests_rel_dir + 'test_a/test_a.check_1') + assert suite.name == tests_rel_dir + 'test_a/test_a.check_1' + assert all(isinstance(n, TestSuite) for n in class_testplan.testsuites.values()) + +@pytest.mark.parametrize("board_root_dir", [("board_config_file_not_exist"), ("board_config")]) +def test_add_configurations_short(test_data, class_env, board_root_dir): + """ Testing add_configurations function of TestPlan class in Twister + Test : Asserting on default platforms list + """ + class_env.board_roots = [os.path.abspath(test_data + board_root_dir)] + plan = TestPlan(class_env) + plan.parse_configuration(config_file=class_env.test_config) + if board_root_dir == "board_config": + plan.add_configurations() + assert sorted(plan.default_platforms) == sorted(['demo_board_1', 'demo_board_3']) + elif board_root_dir == "board_config_file_not_exist": + plan.add_configurations() + assert sorted(plan.default_platforms) != sorted(['demo_board_1']) + + +def test_get_all_testsuites_short(class_testplan, all_testsuites_dict): + """ Testing get_all_testsuites function of TestPlan class in Twister """ + plan = class_testplan + plan.testsuites = all_testsuites_dict + expected_tests = ['sample_test.app', 'test_a.check_1.1a', + 'test_a.check_1.1c', + 'test_a.check_1.2a', 'test_a.check_1.2b', + 'test_a.check_1.Unit_1c', 'test_a.check_1.unit_1a', + 'test_a.check_1.unit_1b', 'test_a.check_2.1a', + 'test_a.check_2.1c', 'test_a.check_2.2a', + 'test_a.check_2.2b', 'test_a.check_2.Unit_1c', + 'test_a.check_2.unit_1a', 'test_a.check_2.unit_1b', + 'test_b.check_1', 'test_b.check_2', 'test_c.check_1', + 'test_c.check_2', 'test_d.check_1.unit_1a', + 'test_d.check_1.unit_1b', + 'test_e.check_1.1a', 'test_e.check_1.1b', + 'test_config.main'] + + assert sorted(plan.get_all_tests()) == sorted(expected_tests) + +def test_get_platforms_short(class_testplan, platforms_list): + """ Testing get_platforms function of TestPlan class in Twister """ + plan = class_testplan + plan.platforms = platforms_list + platform = plan.get_platform("demo_board_1") + assert isinstance(platform, Platform) + assert platform.name == "demo_board_1" + +TESTDATA_PART1 = [ + ("toolchain_allow", ['gcc'], None, None, "Not in testsuite toolchain allow list"), + ("platform_allow", ['demo_board_1'], None, None, "Not in testsuite platform allow list"), + ("toolchain_exclude", ['zephyr'], None, None, "In test case toolchain exclude"), + ("platform_exclude", ['demo_board_2'], None, None, "In test case platform exclude"), + ("arch_exclude", ['x86_demo'], None, None, "In test case arch exclude"), + ("arch_allow", ['arm'], None, None, "Not in test case arch allow list"), + ("skip", True, None, None, "Skip filter"), + ("tags", set(['sensor', 'bluetooth']), "ignore_tags", ['bluetooth'], "Excluded tags per platform (exclude_tags)"), + ("min_flash", "2024", "flash", "1024", "Not enough FLASH"), + ("min_ram", "500", "ram", "256", "Not enough RAM"), + ("None", "None", "env", ['BSIM_OUT_PATH', 'demo_env'], "Environment (BSIM_OUT_PATH, demo_env) not satisfied"), + ("build_on_all", True, None, None, "Platform is excluded on command line."), + (None, None, "supported_toolchains", ['gcc'], "Not supported by the toolchain"), +] + + +@pytest.mark.parametrize("tc_attribute, tc_value, plat_attribute, plat_value, expected_discards", + TESTDATA_PART1) +def test_apply_filters_part1(class_testplan, all_testsuites_dict, platforms_list, + tc_attribute, tc_value, plat_attribute, plat_value, expected_discards): + """ Testing apply_filters function of TestPlan class in Twister + Part 1: Response of apply_filters function have + appropriate values according to the filters + """ + plan = class_testplan + if tc_attribute is None and plat_attribute is None: + plan.apply_filters() + + plan.platforms = platforms_list + plan.platform_names = [p.name for p in platforms_list] + plan.testsuites = all_testsuites_dict + for plat in plan.platforms: + if plat_attribute == "ignore_tags": + plat.ignore_tags = plat_value + if plat_attribute == "flash": + plat.flash = plat_value + if plat_attribute == "ram": + plat.ram = plat_value + if plat_attribute == "env": + plat.env = plat_value + plat.env_satisfied = False + if plat_attribute == "supported_toolchains": + plat.supported_toolchains = plat_value + for _, testcase in plan.testsuites.items(): + if tc_attribute == "toolchain_allow": + testcase.toolchain_allow = tc_value + if tc_attribute == "platform_allow": + testcase.platform_allow = tc_value + if tc_attribute == "toolchain_exclude": + testcase.toolchain_exclude = tc_value + if tc_attribute == "platform_exclude": + testcase.platform_exclude = tc_value + if tc_attribute == "arch_exclude": + testcase.arch_exclude = tc_value + if tc_attribute == "arch_allow": + testcase.arch_allow = tc_value + if tc_attribute == "skip": + testcase.skip = tc_value + if tc_attribute == "tags": + testcase.tags = tc_value + if tc_attribute == "min_flash": + testcase.min_flash = tc_value + if tc_attribute == "min_ram": + testcase.min_ram = tc_value + + if tc_attribute == "build_on_all": + for _, testcase in plan.testsuites.items(): + testcase.build_on_all = tc_value + plan.apply_filters(exclude_platform=['demo_board_1']) + elif plat_attribute == "supported_toolchains": + plan.apply_filters(force_toolchain=False, + exclude_platform=['demo_board_1'], + platform=['demo_board_2']) + elif tc_attribute is None and plat_attribute is None: + plan.apply_filters() + else: + plan.apply_filters(exclude_platform=['demo_board_1'], + platform=['demo_board_2']) + + filtered_instances = list(filter(lambda item: item.status == "filtered", plan.instances.values())) + for d in filtered_instances: + assert d.reason == expected_discards + +TESTDATA_PART2 = [ + ("runnable", "True", "Not runnable on device"), + ("exclude_tag", ['test_a'], "Command line testsuite exclude filter"), + ("run_individual_tests", ['scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1'], "TestSuite name filter"), + ("arch", ['arm_test'], "Command line testsuite arch filter"), + ("tag", ['test_d'], "Command line testsuite tag filter") + ] + + +@pytest.mark.parametrize("extra_filter, extra_filter_value, expected_discards", TESTDATA_PART2) +def test_apply_filters_part2(class_testplan, all_testsuites_dict, + platforms_list, extra_filter, extra_filter_value, expected_discards): + """ Testing apply_filters function of TestPlan class in Twister + Part 2 : Response of apply_filters function (discard dictionary) have + appropriate values according to the filters + """ + + class_testplan.platforms = platforms_list + class_testplan.platform_names = [p.name for p in platforms_list] + class_testplan.testsuites = all_testsuites_dict + kwargs = { + extra_filter : extra_filter_value, + "exclude_platform" : [ + 'demo_board_1' + ], + "platform" : [ + 'demo_board_2' + ] + } + class_testplan.apply_filters(**kwargs) + filtered_instances = list(filter(lambda item: item.status == "filtered", class_testplan.instances.values())) + for d in filtered_instances: + assert d.reason == expected_discards + + +TESTDATA_PART3 = [ + (20, 20, -1, 0), + (-2, -1, 10, 20), + (0, 0, 0, 0) + ] + +@pytest.mark.parametrize("tc_min_flash, plat_flash, tc_min_ram, plat_ram", + TESTDATA_PART3) +def test_apply_filters_part3(class_testplan, all_testsuites_dict, platforms_list, + tc_min_flash, plat_flash, tc_min_ram, plat_ram): + """ Testing apply_filters function of TestPlan class in Twister + Part 3 : Testing edge cases for ram and flash values of platforms & testsuites + """ + class_testplan.platforms = platforms_list + class_testplan.platform_names = [p.name for p in platforms_list] + class_testplan.testsuites = all_testsuites_dict + + for plat in class_testplan.platforms: + plat.flash = plat_flash + plat.ram = plat_ram + for _, testcase in class_testplan.testsuites.items(): + testcase.min_ram = tc_min_ram + testcase.min_flash = tc_min_flash + class_testplan.apply_filters(exclude_platform=['demo_board_1'], + platform=['demo_board_2']) + + filtered_instances = list(filter(lambda item: item.status == "filtered", class_testplan.instances.values())) + assert not filtered_instances + +def test_add_instances_short(tmp_path, class_env, all_testsuites_dict, platforms_list): + """ Testing add_instances() function of TestPlan class in Twister + Test 1: instances dictionary keys have expected values (Platform Name + Testcase Name) + Test 2: Values of 'instances' dictionary in Testsuite class are an + instance of 'TestInstance' class + Test 3: Values of 'instances' dictionary have expected values. + """ + class_env.outdir = tmp_path + plan = TestPlan(class_env) + plan.platforms = platforms_list + platform = plan.get_platform("demo_board_2") + instance_list = [] + for _, testcase in all_testsuites_dict.items(): + instance = TestInstance(testcase, platform, class_env.outdir) + instance_list.append(instance) + plan.add_instances(instance_list) + assert list(plan.instances.keys()) == \ + [platform.name + '/' + s for s in list(all_testsuites_dict.keys())] + assert all(isinstance(n, TestInstance) for n in list(plan.instances.values())) + assert list(plan.instances.values()) == instance_list + + +QUARANTINE_BASIC = { + 'demo_board_1/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1' : 'a1 on board_1 and board_3', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1' : 'a1 on board_1 and board_3' +} + +QUARANTINE_WITH_REGEXP = { + 'demo_board_2/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_2' : 'a2 and c2 on x86', + 'demo_board_1/scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1' : 'all test_d', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1' : 'all test_d', + 'demo_board_2/scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1' : 'all test_d', + 'demo_board_2/scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_2' : 'a2 and c2 on x86' +} + +QUARANTINE_PLATFORM = { + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1' : 'all on board_3', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_2' : 'all on board_3', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1' : 'all on board_3', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_b/test_b.check_1' : 'all on board_3', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_b/test_b.check_2' : 'all on board_3', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_1' : 'all on board_3', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_2' : 'all on board_3', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_e/test_e.check_1' : 'all on board_3', + 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_config/test_config.main' : 'all on board_3' +} + +QUARANTINE_MULTIFILES = { + **QUARANTINE_BASIC, + **QUARANTINE_WITH_REGEXP +} + +@pytest.mark.parametrize( + ("quarantine_files, quarantine_verify, expected_val"), + [ + (['basic.yaml'], False, QUARANTINE_BASIC), + (['with_regexp.yaml'], False, QUARANTINE_WITH_REGEXP), + (['with_regexp.yaml'], True, QUARANTINE_WITH_REGEXP), + (['platform.yaml'], False, QUARANTINE_PLATFORM), + (['basic.yaml', 'with_regexp.yaml'], False, QUARANTINE_MULTIFILES), + (['empty.yaml'], False, {}) + ], + ids=[ + 'basic', + 'with_regexp', + 'quarantine_verify', + 'platform', + 'multifiles', + 'empty' + ]) +def test_quarantine_short(class_testplan, platforms_list, test_data, + quarantine_files, quarantine_verify, expected_val): + """ Testing quarantine feature in Twister + """ + class_testplan.options.all = True + class_testplan.platforms = platforms_list + class_testplan.platform_names = [p.name for p in platforms_list] + class_testplan.TESTSUITE_FILENAME = 'test_data.yaml' + class_testplan.add_testsuites() + + quarantine_list = [ + os.path.join(test_data, 'quarantines', quarantine_file) for quarantine_file in quarantine_files + ] + class_testplan.quarantine = Quarantine(quarantine_list) + class_testplan.options.quarantine_verify = quarantine_verify + class_testplan.apply_filters() + + for testname, instance in class_testplan.instances.items(): + if quarantine_verify: + if testname in expected_val: + assert not instance.status + else: + assert instance.status == 'filtered' + assert instance.reason == "Not under quarantine" + else: + if testname in expected_val: + assert instance.status == 'filtered' + assert instance.reason == "Quarantine: " + expected_val[testname] + else: + assert not instance.status + + +TESTDATA_PART4 = [ + (os.path.join('test_d', 'test_d.check_1'), ['dummy'], + None, 'Snippet not supported'), + (os.path.join('test_c', 'test_c.check_1'), ['cdc-acm-console'], + 0, None), + (os.path.join('test_d', 'test_d.check_1'), ['dummy', 'cdc-acm-console'], + 2, 'Snippet not supported'), +] + +@pytest.mark.parametrize( + 'testpath, required_snippets, expected_filtered_len, expected_filtered_reason', + TESTDATA_PART4, + ids=['app', 'global', 'multiple'] +) +def test_required_snippets_short( + class_testplan, + all_testsuites_dict, + platforms_list, + testpath, + required_snippets, + expected_filtered_len, + expected_filtered_reason +): + """ Testing required_snippets function of TestPlan class in Twister """ + plan = class_testplan + testpath = os.path.join('scripts', 'tests', 'twister', 'test_data', + 'testsuites', 'tests', testpath) + testsuite = class_testplan.testsuites.get(testpath) + plan.platforms = platforms_list + plan.platform_names = [p.name for p in platforms_list] + plan.testsuites = {testpath: testsuite} + + print(plan.testsuites) + + for _, testcase in plan.testsuites.items(): + testcase.exclude_platform = [] + testcase.required_snippets = required_snippets + testcase.build_on_all = True + + plan.apply_filters() + + filtered_instances = list( + filter(lambda item: item.status == "filtered", plan.instances.values()) + ) + if expected_filtered_len is not None: + assert len(filtered_instances) == expected_filtered_len + if expected_filtered_reason is not None: + for d in filtered_instances: + assert d.reason == expected_filtered_reason + + +def test_testplan_get_level(): + testplan = TestPlan(env=mock.Mock()) + lvl1 = mock.Mock() + lvl1.name = 'a lvl' + lvl2 = mock.Mock() + lvl2.name = 'a lvl' + lvl3 = mock.Mock() + lvl3.name = 'other lvl' + testplan.levels.append(lvl1) + testplan.levels.append(lvl2) + testplan.levels.append(lvl3) + + name = 'a lvl' + + res = testplan.get_level(name) + assert res == lvl1 + + res = testplan.get_level(name) + assert res == lvl1 + + testplan.levels.remove(lvl1) + testplan.levels.remove(lvl2) + + res = testplan.get_level(name) + assert res is None + + +TESTDATA_1 = [ + ('', {}), + ( +"""\ +levels: + - name: lvl1 + adds: + - sc1 + - sc2 + inherits: [] + - name: lvl2 + adds: + - sc1-1 + - sc1-2 + inherits: [lvl1] +""", + { + 'lvl1': ['sc1', 'sc2'], + 'lvl2': ['sc1-1', 'sc1-2', 'sc1', 'sc2'] + } + ), +] + +@pytest.mark.parametrize( + 'config_yaml, expected_scenarios', + TESTDATA_1, + ids=['no config', 'valid config'] +) +def test_testplan_parse_configuration(tmp_path, config_yaml, expected_scenarios): + testplan = TestPlan(env=mock.Mock()) + testplan.scenarios = ['sc1', 'sc1-1', 'sc1-2', 'sc2'] + + tmp_config_file = tmp_path / 'config_file.yaml' + if config_yaml: + tmp_config_file.write_text(config_yaml) + + with pytest.raises(TwisterRuntimeError) if not config_yaml else nullcontext(): + testplan.parse_configuration(tmp_config_file) + + if not testplan.levels: + assert expected_scenarios == {} + for level in testplan.levels: + assert sorted(level.scenarios) == sorted(expected_scenarios[level.name]) + + +TESTDATA_2 = [ + ([], [], False), + (['ts1.tc3'], [], True), + (['ts2.tc2'], ['- ts2'], False), +] + +@pytest.mark.parametrize( + 'sub_tests, expected_outs, expect_error', + TESTDATA_2, + ids=['no subtests', 'subtests not found', 'valid subtests'] +) +def test_testplan_find_subtests( + capfd, + sub_tests, + expected_outs, + expect_error +): + testplan = TestPlan(env=mock.Mock()) + testplan.options = mock.Mock(sub_test=sub_tests) + testplan.run_individual_testsuite = [] + testplan.testsuites = { + 'ts1': mock.Mock( + testcases=[ + mock.Mock(), + mock.Mock(), + ] + ), + 'ts2': mock.Mock( + testcases=[ + mock.Mock(), + mock.Mock(), + mock.Mock(), + ] + ) + } + testplan.testsuites['ts1'].name = 'ts1' + testplan.testsuites['ts1'].testcases[0].name = 'ts1.tc1' + testplan.testsuites['ts1'].testcases[1].name = 'ts1.tc2' + testplan.testsuites['ts2'].name = 'ts2' + testplan.testsuites['ts2'].testcases[0].name = 'ts2.tc1' + testplan.testsuites['ts2'].testcases[1].name = 'ts2.tc2' + testplan.testsuites['ts2'].testcases[2].name = 'ts2.tc3' + + with pytest.raises(TwisterRuntimeError) if expect_error else nullcontext(): + testplan.find_subtests() + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stdout.write(err) + + assert all([printout in out for printout in expected_outs]) + + +TESTDATA_3 = [ + (0, 0, [], False, [], TwisterRuntimeError, []), + (1, 1, [], False, [], TwisterRuntimeError, []), + (1, 0, [], True, [], TwisterRuntimeError, ['No quarantine list given to be verified']), +# (1, 0, ['qfile.yaml'], False, ['# empty'], None, ['Quarantine file qfile.yaml is empty']), + (1, 0, ['qfile.yaml'], False, ['- platforms:\n - demo_board_3\n comment: "board_3"'], None, []), +] + +@pytest.mark.parametrize( + 'added_testsuite_count, load_errors, ql, qv, ql_data, exception, expected_logs', + TESTDATA_3, + ids=['no tests', 'load errors', 'quarantine verify without quarantine list', +# 'empty quarantine file', + 'valid quarantine file'] +) +def test_testplan_discover( + tmp_path, + caplog, + added_testsuite_count, + load_errors, + ql, + qv, + ql_data, + exception, + expected_logs +): + for qf, data in zip(ql, ql_data): + tmp_qf = tmp_path / qf + tmp_qf.write_text(data) + + testplan = TestPlan(env=mock.Mock()) + testplan.options = mock.Mock( + test='ts1', + quarantine_list=[tmp_path / qf for qf in ql], + quarantine_verify=qv, + ) + testplan.testsuites = { + 'ts1': mock.Mock(id=1), + 'ts2': mock.Mock(id=2), + } + testplan.run_individual_testsuite = 'ts0' + testplan.load_errors = load_errors + testplan.add_testsuites = mock.Mock(return_value=added_testsuite_count) + testplan.find_subtests = mock.Mock() + testplan.report_duplicates = mock.Mock() + testplan.parse_configuration = mock.Mock() + testplan.add_configurations = mock.Mock() + + with pytest.raises(exception) if exception else nullcontext(): + testplan.discover() + + testplan.add_testsuites.assert_called_once_with(testsuite_filter='ts1') + assert all([log in caplog.text for log in expected_logs]) + + +TESTDATA_4 = [ + (None, None, None, None, '00', + TwisterRuntimeError, [], []), + (None, True, None, None, '6/4', + TwisterRuntimeError, set(['t-p3', 't-p4', 't-p1', 't-p2']), []), + (None, None, 'load_tests.json', None, '0/4', + TwisterRuntimeError, set(['lt-p1', 'lt-p3', 'lt-p4', 'lt-p2']), []), + ('suffix', None, None, True, '2/4', + None, set(['ts-p4', 'ts-p2', 'ts-p3']), [2, 4]), +] + +@pytest.mark.parametrize( + 'report_suffix, only_failed, load_tests, test_only, subset,' \ + ' exception, expected_selected_platforms, expected_generate_subset_args', + TESTDATA_4, + ids=['apply_filters only', 'only failed', 'load tests', 'test only'] +) +def test_testplan_load( + tmp_path, + report_suffix, + only_failed, + load_tests, + test_only, + subset, + exception, + expected_selected_platforms, + expected_generate_subset_args +): + twister_json = """\ +{ + "testsuites": [ + { + "name": "ts1", + "platform": "t-p1", + "testcases": [] + }, + { + "name": "ts1", + "platform": "t-p2", + "testcases": [] + }, + { + "name": "ts2", + "platform": "t-p3", + "testcases": [] + }, + { + "name": "ts2", + "platform": "t-p4", + "testcases": [] + } + ] +} +""" + twister_file = tmp_path / 'twister.json' + twister_file.write_text(twister_json) + + twister_suffix_json = """\ +{ + "testsuites": [ + { + "name": "ts1", + "platform": "ts-p1", + "testcases": [] + }, + { + "name": "ts1", + "platform": "ts-p2", + "testcases": [] + }, + { + "name": "ts2", + "platform": "ts-p3", + "testcases": [] + }, + { + "name": "ts2", + "platform": "ts-p4", + "testcases": [] + } + ] +} +""" + twister_suffix_file = tmp_path / 'twister_suffix.json' + twister_suffix_file.write_text(twister_suffix_json) + + load_tests_json = """\ +{ + "testsuites": [ + { + "name": "ts1", + "platform": "lt-p1", + "testcases": [] + }, + { + "name": "ts1", + "platform": "lt-p2", + "testcases": [] + }, + { + "name": "ts2", + "platform": "lt-p3", + \"testcases": [] + }, + { + "name": "ts2", + "platform": "lt-p4", + "testcases": [] + } + ] +} +""" + load_tests_file = tmp_path / 'load_tests.json' + load_tests_file.write_text(load_tests_json) + + testplan = TestPlan(env=mock.Mock(outdir=tmp_path)) + testplan.testsuites = { + 'ts1': mock.Mock(testcases=[], extra_configs=[]), + 'ts2': mock.Mock(testcases=[], extra_configs=[]), + } + testplan.testsuites['ts1'].name = 'ts1' + testplan.testsuites['ts2'].name = 'ts2' + testplan.options = mock.Mock( + outdir=tmp_path, + report_suffix=report_suffix, + only_failed=only_failed, + load_tests=tmp_path / load_tests if load_tests else None, + test_only=test_only, + exclude_platform=['t-p0', 't-p1', + 'ts-p0', 'ts-p1', + 'lt-p0', 'lt-p1'], + platform=['t-p1', 't-p2', 't-p3', 't-p4', + 'ts-p1', 'ts-p2', 'ts-p3', 'ts-p4', + 'lt-p1', 'lt-p2', 'lt-p3', 'lt-p4'], + subset=subset + ) + testplan.platforms=[mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock(), + mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock(), + mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock()] + testplan.platforms[0].name = 't-p1' + testplan.platforms[1].name = 't-p2' + testplan.platforms[2].name = 't-p3' + testplan.platforms[3].name = 't-p4' + testplan.platforms[4].name = 'ts-p1' + testplan.platforms[5].name = 'ts-p2' + testplan.platforms[6].name = 'ts-p3' + testplan.platforms[7].name = 'ts-p4' + testplan.platforms[8].name = 'lt-p1' + testplan.platforms[9].name = 'lt-p2' + testplan.platforms[10].name = 'lt-p3' + testplan.platforms[11].name = 'lt-p4' + testplan.generate_subset = mock.Mock() + testplan.apply_filters = mock.Mock() + + with mock.patch('twisterlib.testinstance.TestInstance.create_overlay', mock.Mock()), \ + pytest.raises(exception) if exception else nullcontext(): + testplan.load() + + assert testplan.selected_platforms == expected_selected_platforms + if expected_generate_subset_args: + testplan.generate_subset.assert_called_once_with(*expected_generate_subset_args) + else: + testplan.generate_subset.assert_not_called() + + +TESTDATA_5 = [ + (False, False, None, 1, 2, + ['plat1/testA', 'plat1/testB', 'plat1/testC', + 'plat3/testA', 'plat3/testB', 'plat3/testC']), + (False, False, None, 1, 5, + ['plat1/testA', + 'plat3/testA', 'plat3/testB', 'plat3/testC']), + (False, False, None, 2, 2, + ['plat2/testA', 'plat2/testB']), + (True, False, None, 1, 2, + ['plat1/testA', 'plat2/testA', 'plat1/testB', + 'plat3/testA', 'plat3/testB', 'plat3/testC']), + (True, False, None, 2, 2, + ['plat2/testB', 'plat1/testC']), + (True, True, 123, 1, 2, + ['plat2/testA', 'plat2/testB', 'plat1/testC', + 'plat3/testB', 'plat3/testA', 'plat3/testC']), + (True, True, 123, 2, 2, + ['plat1/testB', 'plat1/testA']), +] + +@pytest.mark.parametrize( + 'device_testing, shuffle, seed, subset, sets, expected_subset', + TESTDATA_5, + ids=['subset 1', 'subset 1 out of 5', 'subset 2', + 'device testing, subset 1', 'device testing, subset 2', + 'device testing, shuffle with seed, subset 1', + 'device testing, shuffle with seed, subset 2'] +) +def test_testplan_generate_subset( + device_testing, + shuffle, + seed, + subset, + sets, + expected_subset +): + testplan = TestPlan(env=mock.Mock()) + testplan.options = mock.Mock( + device_testing=device_testing, + shuffle_tests=shuffle, + shuffle_tests_seed=seed + ) + testplan.instances = { + 'plat1/testA': mock.Mock(status=None), + 'plat1/testB': mock.Mock(status=None), + 'plat1/testC': mock.Mock(status=None), + 'plat2/testA': mock.Mock(status=None), + 'plat2/testB': mock.Mock(status=None), + 'plat3/testA': mock.Mock(status='skipped'), + 'plat3/testB': mock.Mock(status='skipped'), + 'plat3/testC': mock.Mock(status='error'), + } + + testplan.generate_subset(subset, sets) + + assert [instance for instance in testplan.instances.keys()] == \ + expected_subset + + +def test_testplan_handle_modules(): + testplan = TestPlan(env=mock.Mock()) + + modules = [mock.Mock(meta={'name': 'name1'}), + mock.Mock(meta={'name': 'name2'})] + + with mock.patch('twisterlib.testplan.parse_modules', return_value=modules): + testplan.handle_modules() + + assert testplan.modules == ['name1', 'name2'] + + +TESTDATA_6 = [ + (True, False, False, 0, 'report_test_tree'), + (True, True, False, 0, 'report_test_tree'), + (True, False, True, 0, 'report_test_tree'), + (True, True, True, 0, 'report_test_tree'), + (False, True, False, 0, 'report_test_list'), + (False, True, True, 0, 'report_test_list'), + (False, False, True, 0, 'report_tag_list'), + (False, False, False, 1, None), +] + +@pytest.mark.parametrize( + 'test_tree, list_tests, list_tags, expected_res, expected_method', + TESTDATA_6, + ids=['test tree', 'test tree + test list', 'test tree + tag list', + 'test tree + test list + tag list', 'test list', + 'test list + tag list', 'tag list', 'no report'] +) +def test_testplan_report( + test_tree, + list_tests, + list_tags, + expected_res, + expected_method +): + testplan = TestPlan(env=mock.Mock()) + testplan.report_test_tree = mock.Mock() + testplan.report_test_list = mock.Mock() + testplan.report_tag_list = mock.Mock() + + testplan.options = mock.Mock( + test_tree=test_tree, + list_tests=list_tests, + list_tags=list_tags, + ) + + res = testplan.report() + + assert res == expected_res + + methods = ['report_test_tree', 'report_test_list', 'report_tag_list'] + if expected_method: + methods.remove(expected_method) + getattr(testplan, expected_method).assert_called_once() + for method in methods: + getattr(testplan, method).assert_not_called() + + +TESTDATA_7 = [ + ( + [ + mock.Mock( + yamlfile='a.yaml', + scenarios=['scenario1', 'scenario2'] + ), + mock.Mock( + yamlfile='b.yaml', + scenarios=['scenario1'] + ) + ], + TwisterRuntimeError, + 'Duplicated test scenarios found:\n' \ + '- scenario1 found in:\n' \ + ' - a.yaml\n' \ + ' - b.yaml\n', + [] + ), + ( + [ + mock.Mock( + yamlfile='a.yaml', + scenarios=['scenario.a.1', 'scenario.a.2'] + ), + mock.Mock( + yamlfile='b.yaml', + scenarios=['scenario.b.1'] + ) + ], + None, + None, + ['No duplicates found.'] + ), +] + +@pytest.mark.parametrize( + 'testsuites, expected_error, error_msg, expected_logs', + TESTDATA_7, + ids=['a duplicate', 'no duplicates'] +) +def test_testplan_report_duplicates( + capfd, + caplog, + testsuites, + expected_error, + error_msg, + expected_logs +): + def mock_get(name): + return list(filter(lambda x: name in x.scenarios, testsuites)) + + testplan = TestPlan(env=mock.Mock()) + testplan.scenarios = [scenario for testsuite in testsuites \ + for scenario in testsuite.scenarios] + testplan.get_testsuite = mock.Mock(side_effect=mock_get) + + with pytest.raises(expected_error) if expected_error is not None else \ + nullcontext() as err: + testplan.report_duplicates() + + if expected_error: + assert str(err._excinfo[1]) == error_msg + + assert all([log in caplog.text for log in expected_logs]) + + +def test_testplan_report_tag_list(capfd): + testplan = TestPlan(env=mock.Mock()) + testplan.testsuites = { + 'testsuite0': mock.Mock(tags=set(['tag1', 'tag2'])), + 'testsuite1': mock.Mock(tags=set(['tag1', 'tag2', 'tag3'])), + 'testsuite2': mock.Mock(tags=set(['tag1', 'tag3'])), + 'testsuite3': mock.Mock(tags=set(['tag'])) + } + + testplan.report_tag_list() + + out,err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert '- tag' in out + assert '- tag1' in out + assert '- tag2' in out + assert '- tag3' in out + + +def test_testplan_report_test_tree(capfd): + testplan = TestPlan(env=mock.Mock()) + testplan.get_all_tests = mock.Mock( + return_value=['1.dummy.case.1', '1.dummy.case.2', + '2.dummy.case.1', '2.dummy.case.2', + '3.dummy.case.1', '3.dummy.case.2', + '4.dummy.case.1', '4.dummy.case.2', + '5.dummy.case.1', '5.dummy.case.2', + 'sample.group1.case1', 'sample.group1.case2', + 'sample.group2.case', 'sample.group3.case1', + 'sample.group3.case2', 'sample.group3.case3'] + ) + + testplan.report_test_tree() + + out,err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + expected = """ +Testsuite +├── Samples +│ ├── group1 +│ │ ├── sample.group1.case1 +│ │ └── sample.group1.case2 +│ ├── group2 +│ │ └── sample.group2.case +│ └── group3 +│ ├── sample.group3.case1 +│ ├── sample.group3.case2 +│ └── sample.group3.case3 +└── Tests + ├── 1 + │ └── dummy + │ ├── 1.dummy.case.1 + │ └── 1.dummy.case.2 + ├── 2 + │ └── dummy + │ ├── 2.dummy.case.1 + │ └── 2.dummy.case.2 + ├── 3 + │ └── dummy + │ ├── 3.dummy.case.1 + │ └── 3.dummy.case.2 + ├── 4 + │ └── dummy + │ ├── 4.dummy.case.1 + │ └── 4.dummy.case.2 + └── 5 + └── dummy + ├── 5.dummy.case.1 + └── 5.dummy.case.2 +""" + expected = expected[1:] + + assert expected in out + + +def test_testplan_report_test_list(capfd): + testplan = TestPlan(env=mock.Mock()) + testplan.get_all_tests = mock.Mock( + return_value=['4.dummy.case.1', '4.dummy.case.2', + '3.dummy.case.2', '2.dummy.case.2', + '1.dummy.case.1', '1.dummy.case.2', + '3.dummy.case.1', '2.dummy.case.1', + '5.dummy.case.1', '5.dummy.case.2'] + ) + + testplan.report_test_list() + + out,err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert ' - 1.dummy.case.1\n' \ + ' - 1.dummy.case.2\n' \ + ' - 2.dummy.case.1\n' \ + ' - 2.dummy.case.2\n' \ + ' - 3.dummy.case.1\n' \ + ' - 3.dummy.case.2\n' \ + ' - 4.dummy.case.1\n' \ + ' - 4.dummy.case.2\n' \ + ' - 5.dummy.case.1\n' \ + ' - 5.dummy.case.2\n' \ + '10 total.' in out + + +def test_testplan_config(caplog): + testplan = TestPlan(env=mock.Mock()) + testplan.coverage_platform = 'dummy cov' + + testplan.config() + + assert 'coverage platform: dummy cov' in caplog.text + + +def test_testplan_info(capfd): + TestPlan.info('dummy text') + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert 'dummy text\n' in out + + +TESTDATA_8 = [ + (False, False, ['p1e2', 'p2', 'p3', 'p3@B'], ['p2']), + (False, True, None, None), + (True, False, ['p1e2', 'p2', 'p3', 'p3@B'], ['p3']), +] + +@pytest.mark.parametrize( + 'override_default_platforms, create_duplicate, expected_platform_names, expected_defaults', + TESTDATA_8, + ids=['no override defaults', 'create duplicate', 'override defaults'] +) +def test_testplan_add_configurations( + tmp_path, + override_default_platforms, + create_duplicate, + expected_platform_names, + expected_defaults +): + # tmp_path + # └ boards <- board root + # ├ arch1 + # │ ├ p1 + # │ | ├ p1e1.yaml + # │ | └ p1e2.yaml + # │ └ p2 + # │ ├ p2.yaml + # │ └ p2-1.yaml <- duplicate + # │ └ p2-2.yaml <- load error + # └ arch2 + # └ p3 + # ├ p3.yaml + # └ p3_B.conf + + tmp_board_root_dir = tmp_path / 'boards' + tmp_board_root_dir.mkdir() + + tmp_arch1_dir = tmp_board_root_dir / 'arch1' + tmp_arch1_dir.mkdir() + + tmp_p1_dir = tmp_arch1_dir / 'p1' + tmp_p1_dir.mkdir() + + p1e1_yaml = """\ +identifier: p1e1 +name: Platform 1 Edition 1 +type: native +arch: arch1 +vendor: vendor1 +toolchain: + - zephyr +twister: False +""" + p1e1_yamlfile = tmp_p1_dir / 'p1e1.yaml' + p1e1_yamlfile.write_text(p1e1_yaml) + + p1e2_yaml = """\ +identifier: p1e2 +name: Platform 1 Edition 2 +type: native +arch: arch1 +vendor: vendor1 +toolchain: + - zephyr +""" + p1e2_yamlfile = tmp_p1_dir / 'p1e2.yaml' + p1e2_yamlfile.write_text(p1e2_yaml) + + tmp_p2_dir = tmp_arch1_dir / 'p2' + tmp_p2_dir.mkdir() + + p2_yaml = """\ +identifier: p2 +name: Platform 2 +type: sim +arch: arch1 +vendor: vendor2 +toolchain: + - zephyr +testing: + default: True +""" + p2_yamlfile = tmp_p2_dir / 'p2.yaml' + p2_yamlfile.write_text(p2_yaml) + + if create_duplicate: + p2_yamlfile = tmp_p2_dir / 'p2-1.yaml' + p2_yamlfile.write_text(p2_yaml) + + p2_2_yaml = """\ +testing: + ć#@%!#!#^#@%@:1.0 +identifier: p2_2 +name: Platform 2 2 +type: sim +arch: arch1 +vendor: vendor2 +toolchain: + - zephyr +""" + p2_2_yamlfile = tmp_p2_dir / 'p2-2.yaml' + p2_2_yamlfile.write_text(p2_2_yaml) + + tmp_arch2_dir = tmp_board_root_dir / 'arch2' + tmp_arch2_dir.mkdir() + + tmp_p3_dir = tmp_arch2_dir / 'p3' + tmp_p3_dir.mkdir() + + p3_yaml = """\ +identifier: p3 +name: Platform 3 +type: unit +arch: arch2 +vendor: vendor3 +toolchain: + - zephyr +""" + p3_yamlfile = tmp_p3_dir / 'p3.yaml' + p3_yamlfile.write_text(p3_yaml) + p3_yamlfile = tmp_p3_dir / 'p3_B.conf' + p3_yamlfile.write_text('') + + env = mock.Mock(board_roots=[tmp_board_root_dir]) + + testplan = TestPlan(env=env) + + testplan.test_config = { + 'platforms': { + 'override_default_platforms': override_default_platforms, + 'default_platforms': ['p3', 'p1e1'] + } + } + + with pytest.raises(Exception) if create_duplicate else nullcontext(): + testplan.add_configurations() + + if expected_defaults is not None: + assert sorted(expected_defaults) == sorted(testplan.default_platforms) + if expected_platform_names is not None: + assert sorted(expected_platform_names) == sorted(testplan.platform_names) + + +def test_testplan_get_all_tests(): + testplan = TestPlan(env=mock.Mock()) + tc1 = mock.Mock() + tc1.name = 'tc1' + tc2 = mock.Mock() + tc2.name = 'tc2' + tc3 = mock.Mock() + tc3.name = 'tc3' + tc4 = mock.Mock() + tc4.name = 'tc4' + tc5 = mock.Mock() + tc5.name = 'tc5' + ts1 = mock.Mock(testcases=[tc1, tc2]) + ts2 = mock.Mock(testcases=[tc3, tc4, tc5]) + testplan.testsuites = { + 'ts1': ts1, + 'ts2': ts2 + } + + res = testplan.get_all_tests() + + assert sorted(res) == ['tc1', 'tc2', 'tc3', 'tc4', 'tc5'] + + +TESTDATA_9 = [ + ([], False, 7), + ([], True, 5), + (['good_test/dummy.common.1', 'good_test/dummy.common.2', 'good_test/dummy.common.3'], False, 3), + (['good_test/dummy.common.1', 'good_test/dummy.common.2', 'good_test/dummy.common.3'], True, 0), +] + +@pytest.mark.parametrize( + 'testsuite_filter, use_alt_root, expected_suite_count', + TESTDATA_9, + ids=['no testsuite filter', 'no testsuite filter, alt root', + 'testsuite filter', 'testsuite filter, alt root'] +) +def test_testplan_add_testsuites(tmp_path, testsuite_filter, use_alt_root, expected_suite_count): + # tmp_path + # ├ tests <- test root + # │ ├ good_test + # │ │ └ testcase.yaml + # │ ├ wrong_test + # │ │ └ testcase.yaml + # │ ├ good_sample + # │ │ └ sample.yaml + # │ └ others + # │ └ other.txt + # └ other_tests <- alternate test root + # └ good_test + # └ testcase.yaml + tmp_test_root_dir = tmp_path / 'tests' + tmp_test_root_dir.mkdir() + + tmp_good_test_dir = tmp_test_root_dir / 'good_test' + tmp_good_test_dir.mkdir() + testcase_yaml_1 = """\ +tests: + dummy.common.1: + build_on_all: true + dummy.common.2: + build_on_all: true + dummy.common.3: + build_on_all: true + dummy.special: + build_on_all: false +""" + testfile_1 = tmp_good_test_dir / 'testcase.yaml' + testfile_1.write_text(testcase_yaml_1) + + tmp_bad_test_dir = tmp_test_root_dir / 'wrong_test' + tmp_bad_test_dir.mkdir() + testcase_yaml_2 = """\ +tests: + wrong: + yaml: {]} +""" + testfile_2 = tmp_bad_test_dir / 'testcase.yaml' + testfile_2.write_text(testcase_yaml_2) + + tmp_good_sample_dir = tmp_test_root_dir / 'good_sample' + tmp_good_sample_dir.mkdir() + samplecase_yaml_1 = """\ +tests: + sample.dummy.common.1: + tags: + - samples + sample.dummy.common.2: + tags: + - samples + sample.dummy.special.1: + tags: + - samples +""" + samplefile_1 = tmp_good_sample_dir / 'sample.yaml' + samplefile_1.write_text(samplecase_yaml_1) + + tmp_other_dir = tmp_test_root_dir / 'others' + tmp_other_dir.mkdir() + _ = tmp_other_dir / 'other.txt' + + tmp_alt_test_root_dir = tmp_path / 'other_tests' + tmp_alt_test_root_dir.mkdir() + + tmp_alt_good_test_dir = tmp_alt_test_root_dir / 'good_test' + tmp_alt_good_test_dir.mkdir() + testcase_yaml_3 = """\ +tests: + dummy.alt.1: + build_on_all: true + dummy.alt.2: + build_on_all: true +""" + testfile_3 = tmp_alt_good_test_dir / 'testcase.yaml' + testfile_3.write_text(testcase_yaml_3) + + env = mock.Mock( + test_roots=[tmp_test_root_dir], + alt_config_root=[tmp_alt_test_root_dir] if use_alt_root else [] + ) + + testplan = TestPlan(env=env) + + res = testplan.add_testsuites(testsuite_filter) + + assert res == expected_suite_count + + +def test_testplan_str(): + testplan = TestPlan(env=mock.Mock()) + testplan.name = 'my name' + + res = testplan.__str__() + + assert res == 'my name' + + +TESTDATA_10 = [ + ('a platform', True), + ('other platform', False), +] + +@pytest.mark.parametrize( + 'name, expect_found', + TESTDATA_10, + ids=['platform exists', 'no platform'] +) +def test_testplan_get_platform(name, expect_found): + testplan = TestPlan(env=mock.Mock()) + p1 = mock.Mock() + p1.name = 'some platform' + p2 = mock.Mock() + p2.name = 'a platform' + testplan.platforms = [p1, p2] + + res = testplan.get_platform(name) + + if expect_found: + assert res.name == name + else: + assert res is None + + +TESTDATA_11 = [ + (True, 'runnable'), + (False, 'buildable'), +] + +@pytest.mark.parametrize( + 'device_testing, expected_tfilter', + TESTDATA_11, + ids=['device testing', 'no device testing'] +) +def test_testplan_load_from_file(caplog, device_testing, expected_tfilter): + def get_platform(name): + p = mock.Mock() + p.name = name + return p + + ts1tc1 = mock.Mock() + ts1tc1.name = 'TS1.tc1' + ts1 = mock.Mock(testcases=[ts1tc1]) + ts1.name = 'TestSuite 1' + ts2 = mock.Mock(testcases=[]) + ts2.name = 'TestSuite 2' + ts3tc1 = mock.Mock() + ts3tc1.name = 'TS3.tc1' + ts3tc2 = mock.Mock() + ts3tc2.name = 'TS3.tc2' + ts3 = mock.Mock(testcases=[ts3tc1, ts3tc2]) + ts3.name = 'TestSuite 3' + ts4tc1 = mock.Mock() + ts4tc1.name = 'TS4.tc1' + ts4 = mock.Mock(testcases=[ts4tc1]) + ts4.name = 'TestSuite 4' + ts5 = mock.Mock(testcases=[]) + ts5.name = 'TestSuite 5' + + testplan = TestPlan(env=mock.Mock(outdir=os.path.join('out', 'dir'))) + testplan.options = mock.Mock(device_testing=device_testing, test_only=True) + testplan.testsuites = { + 'TestSuite 1': ts1, + 'TestSuite 2': ts2, + 'TestSuite 3': ts3, + 'TestSuite 4': ts4, + 'TestSuite 5': ts5 + } + + testplan.get_platform = mock.Mock(side_effect=get_platform) + + testplan_data = """\ +{ + "testsuites": [ + { + "name": "TestSuite 1", + "platform": "Platform 1", + "run_id": 1, + "execution_time": 60.00, + "used_ram": 4096, + "available_ram": 12278, + "used_rom": 1024, + "available_rom": 1047552, + "status": "passed", + "reason": "OK", + "testcases": [ + { + "identifier": "TS1.tc1", + "status": "passed", + "reason": "passed", + "execution_time": 60.00, + "log": "" + } + ] + }, + { + "name": "TestSuite 2", + "platform": "Platform 1" + }, + { + "name": "TestSuite 3", + "platform": "Platform 1", + "run_id": 1, + "execution_time": 360.00, + "used_ram": 4096, + "available_ram": 12278, + "used_rom": 1024, + "available_rom": 1047552, + "status": "error", + "reason": "File Not Found Error", + "testcases": [ + { + "identifier": "TS3.tc1", + "status": "error", + "reason": "File Not Found Error.", + "execution_time": 360.00, + "log": "[ERROR]: File 'dummy.yaml' not found!\\nClosing..." + }, + { + "identifier": "TS3.tc2" + } + ] + }, + { + "name": "TestSuite 4", + "platform": "Platform 1", + "execution_time": 360.00, + "used_ram": 4096, + "available_ram": 12278, + "used_rom": 1024, + "available_rom": 1047552, + "status": "skipped", + "reason": "Not in requested test list.", + "testcases": [ + { + "identifier": "TS4.tc1", + "status": "skipped", + "reason": "Not in requested test list.", + "execution_time": 360.00, + "log": "[INFO] Parsing..." + }, + { + "identifier": "TS3.tc2" + } + ] + }, + { + "name": "TestSuite 5", + "platform": "Platform 2" + } + ] +} +""" + + filter_platform = ['Platform 1'] + + check_runnable_mock = mock.Mock(return_value=True) + + with mock.patch('builtins.open', mock.mock_open(read_data=testplan_data)), \ + mock.patch('twisterlib.testinstance.TestInstance.check_runnable', check_runnable_mock), \ + mock.patch('twisterlib.testinstance.TestInstance.create_overlay', mock.Mock()): + testplan.load_from_file('dummy.yaml', filter_platform) + + expected_instances = { + 'Platform 1/TestSuite 1': { + 'metrics': { + 'handler_time': 60.0, + 'used_ram': 4096, + 'used_rom': 1024, + 'available_ram': 12278, + 'available_rom': 1047552 + }, + 'retries': 0, + 'testcases': { + 'TS1.tc1': { + 'status': 'passed', + 'reason': None, + 'duration': 60.0, + 'output': '' + } + } + }, + 'Platform 1/TestSuite 2': { + 'metrics': { + 'handler_time': 0, + 'used_ram': 0, + 'used_rom': 0, + 'available_ram': 0, + 'available_rom': 0 + }, + 'retries': 0, + 'testcases': [] + }, + 'Platform 1/TestSuite 3': { + 'metrics': { + 'handler_time': 360.0, + 'used_ram': 4096, + 'used_rom': 1024, + 'available_ram': 12278, + 'available_rom': 1047552 + }, + 'retries': 1, + 'testcases': { + 'TS3.tc1': { + 'status': 'error', + 'reason': None, + 'duration': 360.0, + 'output': '[ERROR]: File \'dummy.yaml\' not found!\nClosing...' + }, + 'TS3.tc2': { + 'status': None, + 'reason': None, + 'duration': 0, + 'output': '' + } + } + }, + 'Platform 1/TestSuite 4': { + 'metrics': { + 'handler_time': 360.0, + 'used_ram': 4096, + 'used_rom': 1024, + 'available_ram': 12278, + 'available_rom': 1047552 + }, + 'retries': 0, + 'testcases': { + 'TS4.tc1': { + 'status': 'skipped', + 'reason': 'Not in requested test list.', + 'duration': 360.0, + 'output': '[INFO] Parsing...' + } + } + }, + } + + for n, i in testplan.instances.items(): + assert expected_instances[n]['metrics'] == i.metrics + assert expected_instances[n]['retries'] == i.retries + for t in i.testcases: + assert expected_instances[n]['testcases'][str(t)]['status'] == t.status + assert expected_instances[n]['testcases'][str(t)]['reason'] == t.reason + assert expected_instances[n]['testcases'][str(t)]['duration'] == t.duration + assert expected_instances[n]['testcases'][str(t)]['output'] == t.output + + check_runnable_mock.assert_called_with(mock.ANY, expected_tfilter, mock.ANY, mock.ANY) + + expected_logs = [ + 'loading TestSuite 1...', + 'loading TestSuite 2...', + 'loading TestSuite 3...', + 'loading TestSuite 4...', + ] + assert all([log in caplog.text for log in expected_logs]) + + +def test_testplan_add_instances(): + testplan = TestPlan(env=mock.Mock()) + instance1 = mock.Mock() + instance1.name = 'instance 1' + instance2 = mock.Mock() + instance2.name = 'instance 2' + instance_list = [instance1, instance2] + + testplan.add_instances(instance_list) + + assert testplan.instances == { + 'instance 1': instance1, + 'instance 2': instance2, + } + + +def test_testplan_get_testsuite(): + testplan = TestPlan(env=mock.Mock()) + testplan.testsuites = { + 'testsuite0': mock.Mock(testcases=[mock.Mock(), mock.Mock()]), + 'testsuite1': mock.Mock(testcases=[mock.Mock()]), + 'testsuite2': mock.Mock(testcases=[mock.Mock(), mock.Mock()]), + 'testsuite3': mock.Mock(testcases=[]) + } + testplan.testsuites['testsuite0'].testcases[0].name = 'testcase name 0' + testplan.testsuites['testsuite0'].testcases[1].name = 'testcase name 1' + testplan.testsuites['testsuite1'].testcases[0].name = 'sample id' + testplan.testsuites['testsuite2'].testcases[0].name = 'dummy id' + testplan.testsuites['testsuite2'].testcases[1].name = 'sample id' + + id = 'sample id' + + res = testplan.get_testsuite(id) + + assert len(res) == 2 + assert testplan.testsuites['testsuite1'] in res + assert testplan.testsuites['testsuite2'] in res + + +def test_testplan_verify_platforms_existence(caplog): + testplan = TestPlan(env=mock.Mock()) + testplan.platform_names = ['a platform', 'other platform'] + + platform_names = ['other platform', 'some platform'] + log_info = 'PLATFORM ERROR' + + with pytest.raises(SystemExit) as se: + testplan.verify_platforms_existence(platform_names, log_info) + + assert str(se.value) == '2' + assert 'PLATFORM ERROR - unrecognized platform - some platform' + + +TESTDATA_12 = [ + (True), + (False) +] + +@pytest.mark.parametrize( + 'exists', + TESTDATA_12, + ids=['links dir exists', 'links dir does not exist'] +) +def test_testplan_create_build_dir_links(exists): + outdir = os.path.join('out', 'dir') + instances_linked = [] + + def mock_link(links_dir_path, instance): + assert links_dir_path == os.path.join(outdir, 'twister_links') + instances_linked.append(instance) + + instances = { + 'inst0': mock.Mock(status='passed'), + 'inst1': mock.Mock(status='skipped'), + 'inst2': mock.Mock(status='error'), + } + expected_instances = [instances['inst0'], instances['inst2']] + + testplan = TestPlan(env=mock.Mock(outdir=outdir)) + testplan._create_build_dir_link = mock.Mock(side_effect=mock_link) + testplan.instances = instances + + with mock.patch('os.path.exists', return_value=exists), \ + mock.patch('os.mkdir', mock.Mock()) as mkdir_mock: + testplan.create_build_dir_links() + + if not exists: + mkdir_mock.assert_called_once() + + assert expected_instances == instances_linked + + +TESTDATA_13 = [ + ('nt'), + ('Linux') +] + +@pytest.mark.parametrize( + 'os_name', + TESTDATA_13, +) +def test_testplan_create_build_dir_link(os_name): + testplan = TestPlan(env=mock.Mock()) + links_dir_path = os.path.join('links', 'path') + instance_build_dir = os.path.join('some', 'far', 'off', 'build', 'dir') + instance = mock.Mock(build_dir=instance_build_dir) + + def mock_makedirs(path, exist_ok=False): + assert exist_ok + assert path == instance_build_dir + + def mock_symlink(source, target): + assert source == instance_build_dir + assert target == os.path.join('links', 'path', 'test_0') + + def mock_call(cmd, shell=False): + assert shell + assert cmd == ['mklink', '/J', os.path.join('links', 'path', 'test_0'), + instance_build_dir] + + with mock.patch('os.name', os_name), \ + mock.patch('os.symlink', side_effect=mock_symlink), \ + mock.patch('os.makedirs', side_effect=mock_makedirs), \ + mock.patch('subprocess.call', side_effect=mock_call): + testplan._create_build_dir_link(links_dir_path, instance) + + assert instance.build_dir == os.path.join('links', 'path', 'test_0') + assert testplan.link_dir_counter == 1 + + +TESTDATA_14 = [ + ('bad platform', 'dummy reason', [], + 'dummy status', 'dummy reason'), + ('good platform', 'quarantined', [], + 'error', 'quarantined but is one of the integration platforms'), + ('good platform', 'dummy reason', [{'type': 'command line filter'}], + 'dummy status', 'dummy reason'), + ('good platform', 'dummy reason', [{'type': 'Skip filter'}], + 'dummy status', 'dummy reason'), + ('good platform', 'dummy reason', [{'type': 'platform key filter'}], + 'dummy status', 'dummy reason'), + ('good platform', 'dummy reason', [{'type': 'Toolchain filter'}], + 'dummy status', 'dummy reason'), + ('good platform', 'dummy reason', [{'type': 'Module filter'}], + 'dummy status', 'dummy reason'), + ('good platform', 'dummy reason', [{'type': 'testsuite filter'}], + 'error', 'dummy reason but is one of the integration platforms'), +] + +@pytest.mark.parametrize( + 'platform_name, reason, filters,' \ + ' expected_status, expected_reason', + TESTDATA_14, + ids=['wrong platform', 'quarantined', 'command line filtered', + 'skip filtered', 'platform key filtered', 'toolchain filtered', + 'module filtered', 'skip to error change'] +) +def test_change_skip_to_error_if_integration( + platform_name, + reason, + filters, + expected_status, + expected_reason +): + options = mock.Mock() + platform = mock.Mock() + platform.name = platform_name + testsuite = mock.Mock(integration_platforms=['good platform', 'a platform']) + instance = mock.Mock( + testsuite=testsuite, + platform=platform, + filters=filters, + status='dummy status', + reason=reason + ) + + change_skip_to_error_if_integration(options, instance) + + assert instance.status == expected_status + assert instance.reason == expected_reason diff --git a/scripts/tests/twister/test_testplan_class.py b/scripts/tests/twister/test_testplan_class.py deleted file mode 100644 index f825bc82710cae5..000000000000000 --- a/scripts/tests/twister/test_testplan_class.py +++ /dev/null @@ -1,407 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2020 Intel Corporation -# -# SPDX-License-Identifier: Apache-2.0 - -''' -This test file contains testsuites for Testsuite class of twister -''' -import sys -import os -import pytest - -ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") -sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister")) - -from twisterlib.testplan import TestPlan -from twisterlib.testinstance import TestInstance -from twisterlib.testsuite import TestSuite -from twisterlib.platform import Platform -from twisterlib.quarantine import Quarantine - - -def test_testplan_add_testsuites(class_testplan): - """ Testing add_testcase function of Testsuite class in twister """ - # Test 1: Check the list of testsuites after calling add testsuites function is as expected - class_testplan.SAMPLE_FILENAME = 'test_sample_app.yaml' - class_testplan.TESTSUITE_FILENAME = 'test_data.yaml' - class_testplan.add_testsuites() - - tests_rel_dir = 'scripts/tests/twister/test_data/testsuites/tests/' - expected_testsuites = ['test_b.check_1', - 'test_b.check_2', - 'test_c.check_1', - 'test_c.check_2', - 'test_a.check_1', - 'test_a.check_2', - 'test_d.check_1', - 'test_e.check_1', - 'sample_test.app', - 'test_config.main'] - testsuite_list = [] - for key in sorted(class_testplan.testsuites.keys()): - testsuite_list.append(os.path.basename(os.path.normpath(key))) - assert sorted(testsuite_list) == sorted(expected_testsuites) - - # Test 2 : Assert Testcase name is expected & all testsuites values are testcase class objects - suite = class_testplan.testsuites.get(tests_rel_dir + 'test_a/test_a.check_1') - assert suite.name == tests_rel_dir + 'test_a/test_a.check_1' - assert all(isinstance(n, TestSuite) for n in class_testplan.testsuites.values()) - -@pytest.mark.parametrize("board_root_dir", [("board_config_file_not_exist"), ("board_config")]) -def test_add_configurations(test_data, class_env, board_root_dir): - """ Testing add_configurations function of TestPlan class in Twister - Test : Asserting on default platforms list - """ - class_env.board_roots = [os.path.abspath(test_data + board_root_dir)] - plan = TestPlan(class_env) - plan.parse_configuration(config_file=class_env.test_config) - if board_root_dir == "board_config": - plan.add_configurations() - assert sorted(plan.default_platforms) == sorted(['demo_board_1', 'demo_board_3']) - elif board_root_dir == "board_config_file_not_exist": - plan.add_configurations() - assert sorted(plan.default_platforms) != sorted(['demo_board_1']) - - -def test_get_all_testsuites(class_testplan, all_testsuites_dict): - """ Testing get_all_testsuites function of TestPlan class in Twister """ - plan = class_testplan - plan.testsuites = all_testsuites_dict - expected_tests = ['sample_test.app', 'test_a.check_1.1a', - 'test_a.check_1.1c', - 'test_a.check_1.2a', 'test_a.check_1.2b', - 'test_a.check_1.Unit_1c', 'test_a.check_1.unit_1a', - 'test_a.check_1.unit_1b', 'test_a.check_2.1a', - 'test_a.check_2.1c', 'test_a.check_2.2a', - 'test_a.check_2.2b', 'test_a.check_2.Unit_1c', - 'test_a.check_2.unit_1a', 'test_a.check_2.unit_1b', - 'test_b.check_1', 'test_b.check_2', 'test_c.check_1', - 'test_c.check_2', 'test_d.check_1.unit_1a', - 'test_d.check_1.unit_1b', - 'test_e.check_1.1a', 'test_e.check_1.1b', - 'test_config.main'] - print(sorted(plan.get_all_tests())) - print(sorted(expected_tests)) - assert sorted(plan.get_all_tests()) == sorted(expected_tests) - -def test_get_platforms(class_testplan, platforms_list): - """ Testing get_platforms function of TestPlan class in Twister """ - plan = class_testplan - plan.platforms = platforms_list - platform = plan.get_platform("demo_board_1") - assert isinstance(platform, Platform) - assert platform.name == "demo_board_1" - -TESTDATA_PART1 = [ - ("toolchain_allow", ['gcc'], None, None, "Not in testsuite toolchain allow list"), - ("platform_allow", ['demo_board_1'], None, None, "Not in testsuite platform allow list"), - ("toolchain_exclude", ['zephyr'], None, None, "In test case toolchain exclude"), - ("platform_exclude", ['demo_board_2'], None, None, "In test case platform exclude"), - ("arch_exclude", ['x86_demo'], None, None, "In test case arch exclude"), - ("arch_allow", ['arm'], None, None, "Not in test case arch allow list"), - ("skip", True, None, None, "Skip filter"), - ("tags", set(['sensor', 'bluetooth']), "ignore_tags", ['bluetooth'], "Excluded tags per platform (exclude_tags)"), - ("min_flash", "2024", "flash", "1024", "Not enough FLASH"), - ("min_ram", "500", "ram", "256", "Not enough RAM"), - ("None", "None", "env", ['BSIM_OUT_PATH', 'demo_env'], "Environment (BSIM_OUT_PATH, demo_env) not satisfied"), - ("build_on_all", True, None, None, "Platform is excluded on command line."), - (None, None, "supported_toolchains", ['gcc'], "Not supported by the toolchain"), -] - - -@pytest.mark.parametrize("tc_attribute, tc_value, plat_attribute, plat_value, expected_discards", - TESTDATA_PART1) -def test_apply_filters_part1(class_testplan, all_testsuites_dict, platforms_list, - tc_attribute, tc_value, plat_attribute, plat_value, expected_discards): - """ Testing apply_filters function of TestPlan class in Twister - Part 1: Response of apply_filters function have - appropriate values according to the filters - """ - plan = class_testplan - if tc_attribute is None and plat_attribute is None: - plan.apply_filters() - - plan.platforms = platforms_list - plan.platform_names = [p.name for p in platforms_list] - plan.testsuites = all_testsuites_dict - for plat in plan.platforms: - if plat_attribute == "ignore_tags": - plat.ignore_tags = plat_value - if plat_attribute == "flash": - plat.flash = plat_value - if plat_attribute == "ram": - plat.ram = plat_value - if plat_attribute == "env": - plat.env = plat_value - plat.env_satisfied = False - if plat_attribute == "supported_toolchains": - plat.supported_toolchains = plat_value - for _, testcase in plan.testsuites.items(): - if tc_attribute == "toolchain_allow": - testcase.toolchain_allow = tc_value - if tc_attribute == "platform_allow": - testcase.platform_allow = tc_value - if tc_attribute == "toolchain_exclude": - testcase.toolchain_exclude = tc_value - if tc_attribute == "platform_exclude": - testcase.platform_exclude = tc_value - if tc_attribute == "arch_exclude": - testcase.arch_exclude = tc_value - if tc_attribute == "arch_allow": - testcase.arch_allow = tc_value - if tc_attribute == "skip": - testcase.skip = tc_value - if tc_attribute == "tags": - testcase.tags = tc_value - if tc_attribute == "min_flash": - testcase.min_flash = tc_value - if tc_attribute == "min_ram": - testcase.min_ram = tc_value - - if tc_attribute == "build_on_all": - for _, testcase in plan.testsuites.items(): - testcase.build_on_all = tc_value - plan.apply_filters(exclude_platform=['demo_board_1']) - elif plat_attribute == "supported_toolchains": - plan.apply_filters(force_toolchain=False, - exclude_platform=['demo_board_1'], - platform=['demo_board_2']) - elif tc_attribute is None and plat_attribute is None: - plan.apply_filters() - else: - plan.apply_filters(exclude_platform=['demo_board_1'], - platform=['demo_board_2']) - - filtered_instances = list(filter(lambda item: item.status == "filtered", plan.instances.values())) - for d in filtered_instances: - assert d.reason == expected_discards - -TESTDATA_PART2 = [ - ("runnable", "True", "Not runnable on device"), - ("exclude_tag", ['test_a'], "Command line testsuite exclude filter"), - ("run_individual_tests", ['scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1'], "TestSuite name filter"), - ("arch", ['arm_test'], "Command line testsuite arch filter"), - ("tag", ['test_d'], "Command line testsuite tag filter") - ] - - -@pytest.mark.parametrize("extra_filter, extra_filter_value, expected_discards", TESTDATA_PART2) -def test_apply_filters_part2(class_testplan, all_testsuites_dict, - platforms_list, extra_filter, extra_filter_value, expected_discards): - """ Testing apply_filters function of TestPlan class in Twister - Part 2 : Response of apply_filters function (discard dictionary) have - appropriate values according to the filters - """ - - class_testplan.platforms = platforms_list - class_testplan.platform_names = [p.name for p in platforms_list] - class_testplan.testsuites = all_testsuites_dict - kwargs = { - extra_filter : extra_filter_value, - "exclude_platform" : [ - 'demo_board_1' - ], - "platform" : [ - 'demo_board_2' - ] - } - class_testplan.apply_filters(**kwargs) - filtered_instances = list(filter(lambda item: item.status == "filtered", class_testplan.instances.values())) - for d in filtered_instances: - assert d.reason == expected_discards - - -TESTDATA_PART3 = [ - (20, 20, -1, 0), - (-2, -1, 10, 20), - (0, 0, 0, 0) - ] - -@pytest.mark.parametrize("tc_min_flash, plat_flash, tc_min_ram, plat_ram", - TESTDATA_PART3) -def test_apply_filters_part3(class_testplan, all_testsuites_dict, platforms_list, - tc_min_flash, plat_flash, tc_min_ram, plat_ram): - """ Testing apply_filters function of TestPlan class in Twister - Part 3 : Testing edge cases for ram and flash values of platforms & testsuites - """ - class_testplan.platforms = platforms_list - class_testplan.platform_names = [p.name for p in platforms_list] - class_testplan.testsuites = all_testsuites_dict - - for plat in class_testplan.platforms: - plat.flash = plat_flash - plat.ram = plat_ram - for _, testcase in class_testplan.testsuites.items(): - testcase.min_ram = tc_min_ram - testcase.min_flash = tc_min_flash - class_testplan.apply_filters(exclude_platform=['demo_board_1'], - platform=['demo_board_2']) - - filtered_instances = list(filter(lambda item: item.status == "filtered", class_testplan.instances.values())) - assert not filtered_instances - -def test_add_instances(test_data, class_env, all_testsuites_dict, platforms_list): - """ Testing add_instances() function of TestPlan class in Twister - Test 1: instances dictionary keys have expected values (Platform Name + Testcase Name) - Test 2: Values of 'instances' dictionary in Testsuite class are an - instance of 'TestInstance' class - Test 3: Values of 'instances' dictionary have expected values. - """ - class_env.outdir = test_data - plan = TestPlan(class_env) - plan.platforms = platforms_list - platform = plan.get_platform("demo_board_2") - instance_list = [] - for _, testcase in all_testsuites_dict.items(): - instance = TestInstance(testcase, platform, class_env.outdir) - instance_list.append(instance) - plan.add_instances(instance_list) - assert list(plan.instances.keys()) == \ - [platform.name + '/' + s for s in list(all_testsuites_dict.keys())] - assert all(isinstance(n, TestInstance) for n in list(plan.instances.values())) - assert list(plan.instances.values()) == instance_list - - -QUARANTINE_BASIC = { - 'demo_board_1/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1' : 'a1 on board_1 and board_3', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1' : 'a1 on board_1 and board_3' -} - -QUARANTINE_WITH_REGEXP = { - 'demo_board_2/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_2' : 'a2 and c2 on x86', - 'demo_board_1/scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1' : 'all test_d', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1' : 'all test_d', - 'demo_board_2/scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1' : 'all test_d', - 'demo_board_2/scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_2' : 'a2 and c2 on x86' -} - -QUARANTINE_PLATFORM = { - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_1' : 'all on board_3', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_a/test_a.check_2' : 'all on board_3', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1' : 'all on board_3', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_b/test_b.check_1' : 'all on board_3', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_b/test_b.check_2' : 'all on board_3', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_1' : 'all on board_3', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_2' : 'all on board_3', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_e/test_e.check_1' : 'all on board_3', - 'demo_board_3/scripts/tests/twister/test_data/testsuites/tests/test_config/test_config.main' : 'all on board_3' -} - -QUARANTINE_MULTIFILES = { - **QUARANTINE_BASIC, - **QUARANTINE_WITH_REGEXP -} - -@pytest.mark.parametrize( - ("quarantine_files, quarantine_verify, expected_val"), - [ - (['basic.yaml'], False, QUARANTINE_BASIC), - (['with_regexp.yaml'], False, QUARANTINE_WITH_REGEXP), - (['with_regexp.yaml'], True, QUARANTINE_WITH_REGEXP), - (['platform.yaml'], False, QUARANTINE_PLATFORM), - (['basic.yaml', 'with_regexp.yaml'], False, QUARANTINE_MULTIFILES), - (['empty.yaml'], False, {}) - ], - ids=[ - 'basic', - 'with_regexp', - 'quarantine_verify', - 'platform', - 'multifiles', - 'empty' - ]) -def test_quarantine(class_testplan, platforms_list, test_data, - quarantine_files, quarantine_verify, expected_val): - """ Testing quarantine feature in Twister - """ - class_testplan.options.all = True - class_testplan.platforms = platforms_list - class_testplan.platform_names = [p.name for p in platforms_list] - class_testplan.TESTSUITE_FILENAME = 'test_data.yaml' - class_testplan.add_testsuites() - - quarantine_list = [ - os.path.join(test_data, 'quarantines', quarantine_file) for quarantine_file in quarantine_files - ] - class_testplan.quarantine = Quarantine(quarantine_list) - class_testplan.options.quarantine_verify = quarantine_verify - class_testplan.apply_filters() - - for testname, instance in class_testplan.instances.items(): - if quarantine_verify: - if testname in expected_val: - assert not instance.status - else: - assert instance.status == 'filtered' - assert instance.reason == "Not under quarantine" - else: - print(testname) - if testname in expected_val: - assert instance.status == 'filtered' - assert instance.reason == "Quarantine: " + expected_val[testname] - else: - assert not instance.status - -def test_required_snippets_app(class_testplan, all_testsuites_dict, platforms_list): - """ Testing required_snippets function of TestPlan class in Twister - Ensure that app snippets work and are only applied to boards that support the snippet - """ - plan = class_testplan - testsuite = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1') - plan.platforms = platforms_list - plan.platform_names = [p.name for p in platforms_list] - plan.testsuites = {'scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1': testsuite} - - for _, testcase in plan.testsuites.items(): - testcase.exclude_platform = [] - testcase.required_snippets = ['dummy'] - testcase.build_on_all = True - - plan.apply_filters() - - filtered_instances = list(filter(lambda item: item.status == "filtered", plan.instances.values())) - for d in filtered_instances: - assert d.reason == "Snippet not supported" - -def test_required_snippets_global(class_testplan, all_testsuites_dict, platforms_list): - """ Testing required_snippets function of TestPlan class in Twister - Ensure that global snippets work and application does not fail - """ - plan = class_testplan - testsuite = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_1') - plan.platforms = platforms_list - plan.platform_names = [p.name for p in platforms_list] - plan.testsuites = {'scripts/tests/twister/test_data/testsuites/tests/test_c/test_c.check_1': testsuite} - - for _, testcase in plan.testsuites.items(): - testcase.exclude_platform = [] - testcase.required_snippets = ['cdc-acm-console'] - testcase.build_on_all = True - - plan.apply_filters() - - filtered_instances = list(filter(lambda item: item.status == "filtered", plan.instances.values())) - assert len(filtered_instances) == 0 - -def test_required_snippets_multiple(class_testplan, all_testsuites_dict, platforms_list): - """ Testing required_snippets function of TestPlan class in Twister - Ensure that multiple snippets can be used and are applied - """ - plan = class_testplan - testsuite = class_testplan.testsuites.get('scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1') - plan.platforms = platforms_list - plan.platform_names = [p.name for p in platforms_list] - plan.testsuites = {'scripts/tests/twister/test_data/testsuites/tests/test_d/test_d.check_1': testsuite} - - for _, testcase in plan.testsuites.items(): - testcase.exclude_platform = [] - testcase.required_snippets = ['dummy', 'cdc-acm-console'] - testcase.build_on_all = True - - plan.apply_filters() - - filtered_instances = list(filter(lambda item: item.status == "filtered", plan.instances.values())) - assert len(filtered_instances) == 2 - for d in filtered_instances: - assert d.reason == "Snippet not supported" diff --git a/scripts/tests/twister_blackbox/conftest.py b/scripts/tests/twister_blackbox/conftest.py index f07980a19bce810..95fd0b3338aff2f 100644 --- a/scripts/tests/twister_blackbox/conftest.py +++ b/scripts/tests/twister_blackbox/conftest.py @@ -6,6 +6,7 @@ '''Common fixtures for use in testing the twister tool.''' import logging +import shutil import mock import os import pytest @@ -43,3 +44,28 @@ def clear_log(): handlers = getattr(logger, 'handlers', []) for handler in handlers: logger.removeHandler(handler) + +# This fixture provides blackbox tests with an `out_path` parameter +# It should be used as the `-O` (`--out_dir`) parameter in blackbox tests +# APPRECIATED: method of using this out_path wholly outside of test code +@pytest.fixture(name='out_path', autouse=True) +def provide_out(tmp_path, request): + # As this fixture is autouse, one can use the pytest.mark.noclearout decorator + # in order to be sure that this fixture's code will not fire. + # Most of the time, just omitting the `out_path` parameter is sufficient. + if 'noclearout' in request.keywords: + yield + return + + # Before + out_container_path = tmp_path / 'blackbox-out-container' + out_container_path.mkdir() + out_path = os.path.join(out_container_path, "blackbox-out") + + # Test + yield out_path + + # After + # We're operating in temp, so it is not strictly necessary + # but the files can get large quickly as we do not need them after the test. + shutil.rmtree(out_container_path) diff --git a/scripts/tests/twister_blackbox/test_hardwaremap.py b/scripts/tests/twister_blackbox/test_hardwaremap.py index c5dbd990377bfab..c1efd5be495310a 100644 --- a/scripts/tests/twister_blackbox/test_hardwaremap.py +++ b/scripts/tests/twister_blackbox/test_hardwaremap.py @@ -105,15 +105,14 @@ def setup_class(cls): def teardown_class(cls): pass - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( ('manufacturer', 'product', 'serial', 'runner'), TESTDATA_1, ) - def test_generate(self, capfd, manufacturer, product, serial, runner): + def test_generate(self, capfd, out_path, manufacturer, product, serial, runner): file_name = "test-map.yaml" path = os.path.join(ZEPHYR_BASE, file_name) - args = ['--generate-hardware-map', file_name] + args = ['--outdir', out_path, '--generate-hardware-map', file_name] if os.path.exists(path): os.remove(path) @@ -165,15 +164,14 @@ def mocked_comports(): for handler in handlers: logger.removeHandler(handler) - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( ('manufacturer', 'product', 'serial', 'runner'), TESTDATA_2, ) - def test_few_generate(self, capfd, manufacturer, product, serial, runner): + def test_few_generate(self, capfd, out_path, manufacturer, product, serial, runner): file_name = "test-map.yaml" path = os.path.join(ZEPHYR_BASE, file_name) - args = ['--generate-hardware-map', file_name] + args = ['--outdir', out_path, '--generate-hardware-map', file_name] if os.path.exists(path): os.remove(path) @@ -247,15 +245,14 @@ def mocked_comports(): assert str(sys_exit.value) == '0' - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( ('manufacturer', 'product', 'serial', 'location'), TESTDATA_3, ) - def test_texas_exeption(self, capfd, manufacturer, product, serial, location): + def test_texas_exeption(self, capfd, out_path, manufacturer, product, serial, location): file_name = "test-map.yaml" path = os.path.join(ZEPHYR_BASE, file_name) - args = ['--generate-hardware-map', file_name] + args = ['--outdir', out_path, '--generate-hardware-map', file_name] if os.path.exists(path): os.remove(path) diff --git a/scripts/tests/twister_blackbox/test_printouts.py b/scripts/tests/twister_blackbox/test_printouts.py index 333bf2a090a6bcd..845cea92161291e 100644 --- a/scripts/tests/twister_blackbox/test_printouts.py +++ b/scripts/tests/twister_blackbox/test_printouts.py @@ -11,6 +11,7 @@ import os import pytest import sys +import re from conftest import TEST_DATA, ZEPHYR_BASE, testsuite_filename_mock from twisterlib.testplan import TestPlan @@ -73,6 +74,12 @@ class TestPrintOuts: ), ] + TESTDATA_4 = [ + ( + os.path.join(TEST_DATA, 'tests', 'dummy'), + ['qemu_x86', 'qemu_x86_64', 'frdm_k64f'] + ) + ] @classmethod def setup_class(cls): @@ -81,13 +88,10 @@ def setup_class(cls): cls.spec = importlib.util.spec_from_loader(cls.loader.name, cls.loader) cls.twister_module = importlib.util.module_from_spec(cls.spec) - @classmethod def teardown_class(cls): pass - - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( 'test_path, expected', TESTDATA_1, @@ -96,11 +100,11 @@ def teardown_class(cls): 'tests/dummy/device', ] ) - def test_list_tags(self, capfd, test_path, expected): - args = ['-T', test_path, '--list-tags'] + def test_list_tags(self, capfd, out_path, test_path, expected): + args = ['--outdir', out_path, '-T', test_path, '--list-tags'] with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ - pytest.raises(SystemExit) as sys_exit: + pytest.raises(SystemExit) as sys_exit: self.loader.exec_module(self.twister_module) out, err = capfd.readouterr() @@ -114,8 +118,6 @@ def test_list_tags(self, capfd, test_path, expected): assert str(sys_exit.value) == '0' - - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( 'test_path, expected', TESTDATA_2, @@ -124,11 +126,11 @@ def test_list_tags(self, capfd, test_path, expected): 'tests/dummy/device', ] ) - def test_list_tests(self, capfd, test_path, expected): - args = ['-T', test_path, '--list-tests'] + def test_list_tests(self, capfd, out_path, test_path, expected): + args = ['--outdir', out_path, '-T', test_path, '--list-tests'] with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ - pytest.raises(SystemExit) as sys_exit: + pytest.raises(SystemExit) as sys_exit: self.loader.exec_module(self.twister_module) out, err = capfd.readouterr() @@ -143,8 +145,6 @@ def test_list_tests(self, capfd, test_path, expected): assert str(sys_exit.value) == '0' - - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( 'test_path, expected', TESTDATA_3, @@ -153,11 +153,11 @@ def test_list_tests(self, capfd, test_path, expected): 'tests/dummy/device', ] ) - def test_tree(self, capfd, test_path, expected): - args = ['-T', test_path, '--test-tree'] + def test_tree(self, capfd, out_path, test_path, expected): + args = ['--outdir', out_path, '-T', test_path, '--test-tree'] with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ - pytest.raises(SystemExit) as sys_exit: + pytest.raises(SystemExit) as sys_exit: self.loader.exec_module(self.twister_module) out, err = capfd.readouterr() @@ -166,3 +166,102 @@ def test_tree(self, capfd, test_path, expected): assert expected in out assert str(sys_exit.value) == '0' + + @pytest.mark.usefixtures("clear_log") + @pytest.mark.parametrize( + 'test_path, test_platforms', + TESTDATA_4, + ids=['tests'] + ) + def test_timestamps(self, capfd, out_path, test_path, test_platforms): + + args = ['-i', '--outdir', out_path, '-T', test_path, '--timestamps', '-v'] + \ + [val for pair in zip( + ['-p'] * len(test_platforms), test_platforms + ) for val in pair] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + info_regex = r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} - (?:INFO|DEBUG|ERROR)' + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + output = err.split('\n') + + err_lines = [] + for line in output: + if line.strip(): + + match = re.search(info_regex, line) + if match is None: + err_lines.append(line) + + if err_lines: + assert False, f'No timestamp in line {err_lines}' + assert str(sys_exit.value) == '0' + + @pytest.mark.usefixtures("clear_log") + @pytest.mark.parametrize( + 'flag', + ['--abcd', '--1234', '-%', '-1'] + ) + def test_broken_parameter(self, capfd, flag): + + args = [flag] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + if flag == '-1': + assert str(sys_exit.value) == '1' + else: + assert str(sys_exit.value) == '2' + + @pytest.mark.usefixtures("clear_log") + @pytest.mark.parametrize( + 'flag', + ['--help', '-h'] + ) + def test_help(self, capfd, flag): + args = [flag] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert str(sys_exit.value) == '0' + + @pytest.mark.parametrize( + 'test_path, test_platforms', + TESTDATA_4, + ids=['tests'] + ) + def test_force_color(self, capfd, out_path, test_path, test_platforms): + + args = ['-i', '--outdir', out_path, '-T', test_path, '--force-color'] + \ + [val for pair in zip( + ['-p'] * len(test_platforms), test_platforms + ) for val in pair] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + assert str(sys_exit.value) == '0' diff --git a/scripts/tests/twister_blackbox/test_qemu.py b/scripts/tests/twister_blackbox/test_qemu.py index a7f7d1c33ef162d..087249ccb501650 100644 --- a/scripts/tests/twister_blackbox/test_qemu.py +++ b/scripts/tests/twister_blackbox/test_qemu.py @@ -74,8 +74,6 @@ def setup_class(cls): def teardown_class(cls): pass - - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( 'test_path, test_platforms, expected', TESTDATA_1, @@ -84,8 +82,8 @@ def teardown_class(cls): 'tests/dummy/device', ] ) - def test_emulation_only(self, capfd, test_path, test_platforms, expected): - args = ['-i', '-T', test_path, '--emulation-only'] + \ + def test_emulation_only(self, capfd, out_path, test_path, test_platforms, expected): + args = ['-i', '--outdir', out_path, '-T', test_path, '--emulation-only'] + \ [val for pair in zip( ['-p'] * len(test_platforms), test_platforms ) for val in pair] diff --git a/scripts/tests/twister_blackbox/test_report.py b/scripts/tests/twister_blackbox/test_report.py index aa5a541ff3d14f9..1a076f97b198d3b 100644 --- a/scripts/tests/twister_blackbox/test_report.py +++ b/scripts/tests/twister_blackbox/test_report.py @@ -110,7 +110,6 @@ def setup_class(cls): def teardown_class(cls): pass - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( 'test_path, test_platforms, file_name', TESTDATA_1, @@ -118,14 +117,11 @@ def teardown_class(cls): 'platform_reports' ] ) - def test_platform_reports(self, capfd, test_path, test_platforms, file_name): - args = ['-i', '-T', test_path, '--platform-reports'] + \ + def test_platform_reports(self, capfd, out_path, test_path, test_platforms, file_name): + args = ['-i', '--outdir', out_path, '-T', test_path, '--platform-reports'] + \ [val for pair in zip( ['-p'] * len(test_platforms), test_platforms ) for val in pair] - twister_path = os.path.join(ZEPHYR_BASE, "twister-out") - if os.path.exists(twister_path): - shutil.rmtree(twister_path) with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ pytest.raises(SystemExit) as sys_exit: @@ -136,7 +132,7 @@ def test_platform_reports(self, capfd, test_path, test_platforms, file_name): sys.stderr.write(err) for f_name in file_name: - path = os.path.join(twister_path, f_name) + path = os.path.join(out_path, f_name) assert os.path.exists(path), 'file not found' if path.endswith(".json"): @@ -158,12 +154,11 @@ def test_platform_reports(self, capfd, test_path, test_platforms, file_name): pytest.fail(f"Unsupported file type: '{path}'") for f_platform in test_platforms: - platform_path = os.path.join(twister_path, f_platform) + platform_path = os.path.join(out_path, f_platform) assert os.path.exists(platform_path), f'file not found {f_platform}' assert str(sys_exit.value) == '0' - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( 'test_path, test_platforms, file_name', TESTDATA_2, @@ -171,16 +166,12 @@ def test_platform_reports(self, capfd, test_path, test_platforms, file_name): 'report_suffix', ] ) - def test_report_suffix(self, capfd, test_path, test_platforms, file_name): - args = ['-i', '-T', test_path, '--platform-reports', '--report-suffix=TEST'] + \ + def test_report_suffix(self, capfd, out_path, test_path, test_platforms, file_name): + args = ['-i', '--outdir', out_path, '-T', test_path, '--platform-reports', '--report-suffix=TEST'] + \ [val for pair in zip( ['-p'] * len(test_platforms), test_platforms ) for val in pair] - twister_path = os.path.join(ZEPHYR_BASE, "twister-out") - if os.path.exists(twister_path): - shutil.rmtree(twister_path) - with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ pytest.raises(SystemExit) as sys_exit: self.loader.exec_module(self.twister_module) @@ -190,12 +181,11 @@ def test_report_suffix(self, capfd, test_path, test_platforms, file_name): sys.stderr.write(err) for f_name in file_name: - path = os.path.join(twister_path, f_name) + path = os.path.join(out_path, f_name) assert os.path.exists(path), f'file not found {f_name}' assert str(sys_exit.value) == '0' - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( 'test_path, test_platforms, report_arg, file_name', TESTDATA_3, @@ -205,8 +195,8 @@ def test_report_suffix(self, capfd, test_path, test_platforms, file_name): 'report-name + platform-reports + report-suffix' ] ) - def test_report_name(self, capfd, test_path, test_platforms, report_arg, file_name): - args = ['-i', '-T', test_path] + \ + def test_report_name(self, capfd, out_path, test_path, test_platforms, report_arg, file_name): + args = ['-i', '--outdir', out_path, '-T', test_path] + \ [val for pair in zip( ['-p'] * len(test_platforms), test_platforms ) for val in pair] + \ @@ -214,10 +204,6 @@ def test_report_name(self, capfd, test_path, test_platforms, report_arg, file_na report_arg ) for val in pair] - twister_path = os.path.join(ZEPHYR_BASE, "twister-out") - if os.path.exists(twister_path): - shutil.rmtree(twister_path) - with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ pytest.raises(SystemExit) as sys_exit: self.loader.exec_module(self.twister_module) @@ -227,12 +213,11 @@ def test_report_name(self, capfd, test_path, test_platforms, report_arg, file_na sys.stderr.write(err) for f_name in file_name: - path = os.path.join(twister_path, f_name) + path = os.path.join(out_path, f_name) assert os.path.exists(path), f'file not found {f_name}' assert str(sys_exit.value) == '0' - @pytest.mark.usefixtures("clear_log") @pytest.mark.parametrize( 'test_path, test_platforms, file_name, dir_name', TESTDATA_4, @@ -240,8 +225,8 @@ def test_report_name(self, capfd, test_path, test_platforms, report_arg, file_na 'report_dir', ] ) - def test_report_dir(self, capfd, test_path, test_platforms, file_name, dir_name): - args = ['-i', '-T', test_path, "--report-dir", dir_name] + \ + def test_report_dir(self, capfd, out_path, test_path, test_platforms, file_name, dir_name): + args = ['-i', '--outdir', out_path, '-T', test_path, "--report-dir", dir_name] + \ [val for pair in zip( ['-p'] * len(test_platforms), test_platforms ) for val in pair] @@ -250,21 +235,26 @@ def test_report_dir(self, capfd, test_path, test_platforms, file_name, dir_name) if os.path.exists(twister_path): shutil.rmtree(twister_path) - with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ - pytest.raises(SystemExit) as sys_exit: - self.loader.exec_module(self.twister_module) + try: + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) - out, err = capfd.readouterr() - sys.stdout.write(out) - sys.stderr.write(err) + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) - for f_name in file_name: - path = os.path.join(twister_path, f_name) - assert os.path.exists(path), f'file not found {f_name}' + for f_name in file_name: + path = os.path.join(twister_path, f_name) + assert os.path.exists(path), f'file not found {f_name}' - assert str(sys_exit.value) == '0' + assert str(sys_exit.value) == '0' + finally: + twister_path = os.path.join(ZEPHYR_BASE, dir_name) + if os.path.exists(twister_path): + shutil.rmtree(twister_path) - @pytest.mark.usefixtures("clear_log") + @pytest.mark.noclearout @pytest.mark.parametrize( 'test_path, test_platforms, file_name, dir_name', TESTDATA_5, @@ -290,12 +280,17 @@ def test_outdir(self, capfd, test_path, test_platforms, file_name, dir_name): sys.stdout.write(out) sys.stderr.write(err) - for f_name in file_name: - path = os.path.join(twister_path, f_name) - assert os.path.exists(path), 'file not found {f_name}' + try: + for f_name in file_name: + path = os.path.join(twister_path, f_name) + assert os.path.exists(path), 'file not found {f_name}' - for f_platform in test_platforms: - platform_path = os.path.join(twister_path, f_platform) - assert os.path.exists(platform_path), f'file not found {f_platform}' + for f_platform in test_platforms: + platform_path = os.path.join(twister_path, f_platform) + assert os.path.exists(platform_path), f'file not found {f_platform}' - assert str(sys_exit.value) == '0' + assert str(sys_exit.value) == '0' + finally: + twister_path = os.path.join(ZEPHYR_BASE, dir_name) + if os.path.exists(twister_path): + shutil.rmtree(twister_path) diff --git a/scripts/west_commands/runners/jlink.py b/scripts/west_commands/runners/jlink.py index 4fa717206736e67..17d607877459503 100644 --- a/scripts/west_commands/runners/jlink.py +++ b/scripts/west_commands/runners/jlink.py @@ -5,6 +5,7 @@ '''Runner for debugging with J-Link.''' import argparse +import ipaddress import logging import os from pathlib import Path @@ -25,6 +26,13 @@ DEFAULT_JLINK_EXE = 'JLink.exe' if sys.platform == 'win32' else 'JLinkExe' DEFAULT_JLINK_GDB_PORT = 2331 +def is_ip(ip): + try: + ipaddress.ip_address(ip) + except ValueError: + return False + return True + class ToggleAction(argparse.Action): def __call__(self, parser, args, ignored, option): @@ -80,7 +88,8 @@ def capabilities(cls): @classmethod def dev_id_help(cls) -> str: return '''Device identifier. Use it to select the J-Link Serial Number - of the device connected over USB.''' + of the device connected over USB. If the J-Link is connected over ip, + the Device identifier is the ip.''' @classmethod def tool_opt_help(cls) -> str: @@ -226,9 +235,9 @@ def do_run(self, command, **kwargs): 'RTOSPlugin_Zephyr') server_cmd = ([self.gdbserver] + - # only USB connections supported - ['-select', 'usb' + (f'={self.dev_id}' - if self.dev_id else ''), + ['-select', + ('ip' if is_ip(self.dev_id) else 'usb') + + (f'={self.dev_id}' if self.dev_id else ''), '-port', str(self.gdb_port), '-if', self.iface, '-speed', self.speed, @@ -355,8 +364,7 @@ def flash(self, **kwargs): loader_details = "?" + self.loader cmd = ([self.commander] + - # only USB connections supported - (['-USB', f'{self.dev_id}'] if self.dev_id else []) + + (['-IP', f'{self.dev_id}'] if is_ip(self.dev_id) else (['-USB', f'{self.dev_id}'] if self.dev_id else [])) + (['-nogui', '1'] if self.supports_nogui else []) + ['-if', self.iface, '-speed', self.speed, diff --git a/scripts/west_commands/sign.py b/scripts/west_commands/sign.py index 8d961004adb0578..fb1de57097412c1 100644 --- a/scripts/west_commands/sign.py +++ b/scripts/west_commands/sign.py @@ -438,11 +438,26 @@ def preprocess_toml(self, config_dir, toml_basename, subdir): 'Runs the C pre-processor on config_dir/toml_basename.h' compiler_path = self.cmake_cache.get("CMAKE_C_COMPILER") - preproc_cmd = [compiler_path, '-P', '-E', str(config_dir / (toml_basename + '.h'))] + preproc_cmd = [compiler_path, '-E', str(config_dir / (toml_basename + '.h'))] + # -P removes line markers to keep the .toml output reproducible. To + # trace #includes, temporarily comment out '-P' (-f*-prefix-map + # unfortunately don't seem to make any difference here and they're + # gcc-specific) + preproc_cmd += ['-P'] + + # "REM" escapes _leading_ '#' characters from cpp and allows + # such comments to be preserved in generated/*.toml files: + # + # REM # my comment... + # + # Note _trailing_ '#' characters and comments are ignored by cpp + # and don't need any REM trick. + preproc_cmd += ['-DREM='] + preproc_cmd += ['-I', str(self.sof_src_dir / 'src')] preproc_cmd += ['-imacros', str(pathlib.Path('zephyr') / 'include' / 'generated' / 'autoconf.h')] - preproc_cmd += ['-o', str(subdir / toml_basename)] + preproc_cmd += ['-o', str(subdir / 'rimage_config.toml')] self.command.inf(quote_sh_list(preproc_cmd)) subprocess.run(preproc_cmd, check=True, cwd=self.build_dir) @@ -573,13 +588,12 @@ def sign(self, command, build_dir, build_conf, formats): command.die(f"Cannot have both {toml_basename + '.h'} and {toml_basename} in {conf_dir}") if (conf_dir / (toml_basename + '.h')).exists(): - toml_subdir = pathlib.Path('zephyr') / 'misc' / 'generated' - self.preprocess_toml(conf_dir, toml_basename, toml_subdir) - toml_dir = b / toml_subdir + generated_subdir = pathlib.Path('zephyr') / 'misc' / 'generated' + self.preprocess_toml(conf_dir, toml_basename, generated_subdir) + extra_ri_args += ['-c', str(b / generated_subdir / 'rimage_config.toml')] else: toml_dir = conf_dir - - extra_ri_args += ['-c', str(toml_dir / toml_basename)] + extra_ri_args += ['-c', str(toml_dir / toml_basename)] # Warning: while not officially supported (yet?), the rimage --option that is last # on the command line currently wins in case of duplicate options. So pay diff --git a/scripts/west_commands/zspdx/walker.py b/scripts/west_commands/zspdx/walker.py index c809ac40318d184..0c6469444eda078 100644 --- a/scripts/west_commands/zspdx/walker.py +++ b/scripts/west_commands/zspdx/walker.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import os +import yaml from west import log from west.util import west_topdir, WestNotFound @@ -74,6 +75,11 @@ def makeDocuments(self): log.inf("parsing CMake Cache file") self.getCacheFile() + # check if meta file is generated + if not self.metaFile: + log.err("CONFIG_BUILD_OUTPUT_META must be enabled to generate spdx files; bailing") + return False + # parse codemodel from Walker cfg's build dir log.inf("parsing CMake Codemodel files") self.cm = self.getCodemodel() @@ -108,6 +114,7 @@ def getCacheFile(self): if self.cmakeCache: self.compilerPath = self.cmakeCache.get("CMAKE_C_COMPILER", "") self.sdkPath = self.cmakeCache.get("ZEPHYR_SDK_INSTALL_DIR", "") + self.metaFile = self.cmakeCache.get("KERNEL_META_PATH", "") # determine path from build dir to CMake file-based API index file, then # parse it and return the Codemodel @@ -138,10 +145,35 @@ def getCodemodel(self): # parse it return parseReply(indexFilePath) - # set up Documents before beginning - def setupDocuments(self): - log.dbg("setting up placeholder documents") + def setupAppDocument(self): + # set up app document + cfgApp = DocumentConfig() + cfgApp.name = "app-sources" + cfgApp.namespace = self.cfg.namespacePrefix + "/app" + cfgApp.docRefID = "DocumentRef-app" + self.docApp = Document(cfgApp) + + # also set up app sources package + cfgPackageApp = PackageConfig() + cfgPackageApp.name = "app-sources" + cfgPackageApp.spdxID = "SPDXRef-app-sources" + # relativeBaseDir is app sources dir + cfgPackageApp.relativeBaseDir = self.cm.paths_source + pkgApp = Package(cfgPackageApp, self.docApp) + self.docApp.pkgs[pkgApp.cfg.spdxID] = pkgApp + # create DESCRIBES relationship data + rd = RelationshipData() + rd.ownerType = RelationshipDataElementType.DOCUMENT + rd.ownerDocument = self.docApp + rd.otherType = RelationshipDataElementType.PACKAGEID + rd.otherPackageID = cfgPackageApp.spdxID + rd.rlnType = "DESCRIBES" + + # add it to pending relationships queue + self.pendingRelationships.append(rd) + + def setupBuildDocument(self): # set up build document cfgBuild = DocumentConfig() cfgBuild.name = "build" @@ -163,6 +195,7 @@ def setupDocuments(self): # add it to pending relationships queue self.pendingRelationships.append(rd) + def setupZephyrDocument(self, modules): # set up zephyr document cfgZephyr = DocumentConfig() cfgZephyr.name = "zephyr-sources" @@ -170,19 +203,42 @@ def setupDocuments(self): cfgZephyr.docRefID = "DocumentRef-zephyr" self.docZephyr = Document(cfgZephyr) - # also set up zephyr sources package - cfgPackageZephyr = PackageConfig() - cfgPackageZephyr.name = "zephyr-sources" - cfgPackageZephyr.spdxID = "SPDXRef-zephyr-sources" # relativeBaseDir is Zephyr sources topdir try: - cfgPackageZephyr.relativeBaseDir = west_topdir(self.cm.paths_source) + relativeBaseDir = west_topdir(self.cm.paths_source) except WestNotFound: log.err(f"cannot find west_topdir for CMake Codemodel sources path {self.cm.paths_source}; bailing") return False + + # set up zephyr sources package + cfgPackageZephyr = PackageConfig() + cfgPackageZephyr.name = "zephyr-sources" + cfgPackageZephyr.spdxID = "SPDXRef-zephyr-sources" + cfgPackageZephyr.relativeBaseDir = relativeBaseDir + pkgZephyr = Package(cfgPackageZephyr, self.docZephyr) self.docZephyr.pkgs[pkgZephyr.cfg.spdxID] = pkgZephyr + for module in modules: + module_name = module.get("name", None) + module_path = module.get("path", None) + + if not module_name: + log.err(f"cannot find module name in meta file; bailing") + return False + + # Replace "_" by "-" since it's not allowed in spdx ID + module_name = module_name.replace("_", "-") + + # set up zephyr sources package + cfgPackageZephyrModule = PackageConfig() + cfgPackageZephyrModule.name = module_name + cfgPackageZephyrModule.spdxID = "SPDXRef-" + module_name + "-sources" + cfgPackageZephyrModule.relativeBaseDir = module_path + + pkgZephyrModule = Package(cfgPackageZephyrModule, self.docZephyr) + self.docZephyr.pkgs[pkgZephyrModule.cfg.spdxID] = pkgZephyrModule + # create DESCRIBES relationship data rd = RelationshipData() rd.ownerType = RelationshipDataElementType.DOCUMENT @@ -194,60 +250,52 @@ def setupDocuments(self): # add it to pending relationships queue self.pendingRelationships.append(rd) - # set up app document - cfgApp = DocumentConfig() - cfgApp.name = "app-sources" - cfgApp.namespace = self.cfg.namespacePrefix + "/app" - cfgApp.docRefID = "DocumentRef-app" - self.docApp = Document(cfgApp) - - # also set up app sources package - cfgPackageApp = PackageConfig() - cfgPackageApp.name = "app-sources" - cfgPackageApp.spdxID = "SPDXRef-app-sources" - # relativeBaseDir is app sources dir - cfgPackageApp.relativeBaseDir = self.cm.paths_source - pkgApp = Package(cfgPackageApp, self.docApp) - self.docApp.pkgs[pkgApp.cfg.spdxID] = pkgApp + def setupSDKDocument(self): + # set up SDK document + cfgSDK = DocumentConfig() + cfgSDK.name = "sdk" + cfgSDK.namespace = self.cfg.namespacePrefix + "/sdk" + cfgSDK.docRefID = "DocumentRef-sdk" + self.docSDK = Document(cfgSDK) + + # also set up zephyr sdk package + cfgPackageSDK = PackageConfig() + cfgPackageSDK.name = "sdk" + cfgPackageSDK.spdxID = "SPDXRef-sdk" + # relativeBaseDir is SDK dir + cfgPackageSDK.relativeBaseDir = self.sdkPath + pkgSDK = Package(cfgPackageSDK, self.docSDK) + self.docSDK.pkgs[pkgSDK.cfg.spdxID] = pkgSDK # create DESCRIBES relationship data rd = RelationshipData() rd.ownerType = RelationshipDataElementType.DOCUMENT - rd.ownerDocument = self.docApp + rd.ownerDocument = self.docSDK rd.otherType = RelationshipDataElementType.PACKAGEID - rd.otherPackageID = cfgPackageApp.spdxID + rd.otherPackageID = cfgPackageSDK.spdxID rd.rlnType = "DESCRIBES" # add it to pending relationships queue self.pendingRelationships.append(rd) - if self.cfg.includeSDK: - # set up SDK document - cfgSDK = DocumentConfig() - cfgSDK.name = "sdk" - cfgSDK.namespace = self.cfg.namespacePrefix + "/sdk" - cfgSDK.docRefID = "DocumentRef-sdk" - self.docSDK = Document(cfgSDK) - - # also set up zephyr sdk package - cfgPackageSDK = PackageConfig() - cfgPackageSDK.name = "sdk" - cfgPackageSDK.spdxID = "SPDXRef-sdk" - # relativeBaseDir is SDK dir - cfgPackageSDK.relativeBaseDir = self.sdkPath - pkgSDK = Package(cfgPackageSDK, self.docSDK) - self.docSDK.pkgs[pkgSDK.cfg.spdxID] = pkgSDK - - # create DESCRIBES relationship data - rd = RelationshipData() - rd.ownerType = RelationshipDataElementType.DOCUMENT - rd.ownerDocument = self.docSDK - rd.otherType = RelationshipDataElementType.PACKAGEID - rd.otherPackageID = cfgPackageSDK.spdxID - rd.rlnType = "DESCRIBES" + # set up Documents before beginning + def setupDocuments(self): + log.dbg("setting up placeholder documents") - # add it to pending relationships queue - self.pendingRelationships.append(rd) + self.setupBuildDocument() + + try: + with open(self.metaFile) as file: + content = yaml.load(file.read(), yaml.SafeLoader) + self.setupZephyrDocument(content["modules"]) + except (FileNotFoundError, yaml.YAMLError): + log.err(f"cannot find a valid zephyr_meta.yml required for SPDX generation; bailing") + return False + + self.setupAppDocument() + + if self.cfg.includeSDK: + self.setupSDKDocument() return True @@ -497,6 +545,7 @@ def walkPendingSources(self): # not yet assigned; figure out where it goes pkgBuild = self.findBuildPackage(srcAbspath) + pkgZephyr = self.findZephyrPackage(srcAbspath) if pkgBuild: log.dbg(f" - {srcAbspath}: assigning to build document, package {pkgBuild.cfg.name}") @@ -510,7 +559,7 @@ def walkPendingSources(self): log.dbg(f" - {srcAbspath}: assigning to app document") srcDoc = self.docApp srcPkg = pkgApp - elif os.path.commonpath([srcAbspath, pkgZephyr.cfg.relativeBaseDir]) == pkgZephyr.cfg.relativeBaseDir: + elif pkgZephyr: log.dbg(f" - {srcAbspath}: assigning to zephyr document") srcDoc = self.docZephyr srcPkg = pkgZephyr @@ -533,16 +582,16 @@ def walkPendingSources(self): srcDoc.fileLinks[sf.abspath] = sf self.allFileLinks[sf.abspath] = srcDoc - # figure out which build Package contains the given file, if any + # figure out which Package contains the given file, if any # call with: # 1) absolute path for source filename being searched - def findBuildPackage(self, srcAbspath): + def findPackageFromSrcAbsPath(self, document, srcAbspath): # Multiple target Packages might "contain" the file path, if they # are nested. If so, the one with the longest path would be the # most deeply-nested target directory, so that's the one which # should get the file path. pkgLongestMatch = None - for pkg in self.docBuild.pkgs.values(): + for pkg in document.pkgs.values(): if os.path.commonpath([srcAbspath, pkg.cfg.relativeBaseDir]) == pkg.cfg.relativeBaseDir: # the package does contain this file; is it the deepest? if pkgLongestMatch: @@ -554,6 +603,12 @@ def findBuildPackage(self, srcAbspath): return pkgLongestMatch + def findBuildPackage(self, srcAbspath): + return self.findPackageFromSrcAbsPath(self.docBuild, srcAbspath) + + def findZephyrPackage(self, srcAbspath): + return self.findPackageFromSrcAbsPath(self.docZephyr, srcAbspath) + # walk through pending RelationshipData entries, create corresponding # Relationships, and assign them to the applicable Files / Packages def walkRelationships(self): diff --git a/soc/arm/atmel_sam/same70/Kconfig.series b/soc/arm/atmel_sam/same70/Kconfig.series index 66ceeb6ca3eb8c3..4e7d6aa396e94db 100644 --- a/soc/arm/atmel_sam/same70/Kconfig.series +++ b/soc/arm/atmel_sam/same70/Kconfig.series @@ -14,6 +14,7 @@ config SOC_SERIES_SAME70 select CPU_HAS_ICACHE select CPU_HAS_DCACHE select SOC_FAMILY_SAM + select INIT_ARCH_HW_AT_BOOT select PLATFORM_SPECIFIC_INIT select ASF select HAS_SWO diff --git a/soc/arm/atmel_sam/same70/soc.c b/soc/arm/atmel_sam/same70/soc.c index 79d7c9fa830ee79..f68e520c724e498 100644 --- a/soc/arm/atmel_sam/same70/soc.c +++ b/soc/arm/atmel_sam/same70/soc.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -226,16 +228,19 @@ static ALWAYS_INLINE void clock_init(void) void z_arm_platform_init(void) { - if (IS_ENABLED(CONFIG_CACHE_MANAGEMENT) && IS_ENABLED(CONFIG_ICACHE)) { - SCB_EnableICache(); - } else { - SCB_DisableICache(); - } - if (IS_ENABLED(CONFIG_CACHE_MANAGEMENT) && IS_ENABLED(CONFIG_DCACHE)) { - SCB_EnableDCache(); - } else { - SCB_DisableDCache(); - } + /* + * DTCM is enabled by default at reset, therefore we have to disable + * it first to get the caches into a state where then the + * sys_cache*-functions can enable them, if requested by the + * configuration. + */ + SCB_DisableDCache(); + + /* + * Enable the caches only if configured to do so. + */ + sys_cache_instr_enable(); + sys_cache_data_enable(); /* * Set FWS (Flash Wait State) value before increasing Master Clock diff --git a/soc/arm/atmel_sam/samv71/Kconfig.series b/soc/arm/atmel_sam/samv71/Kconfig.series index 543def9d9a21924..cadee35acb52194 100644 --- a/soc/arm/atmel_sam/samv71/Kconfig.series +++ b/soc/arm/atmel_sam/samv71/Kconfig.series @@ -14,6 +14,7 @@ config SOC_SERIES_SAMV71 select CPU_HAS_ICACHE select CPU_HAS_DCACHE select SOC_FAMILY_SAM + select INIT_ARCH_HW_AT_BOOT select PLATFORM_SPECIFIC_INIT select ASF select HAS_SWO diff --git a/soc/arm/atmel_sam/samv71/soc.c b/soc/arm/atmel_sam/samv71/soc.c index 7571ce46dc71085..f88a3cb440b7955 100644 --- a/soc/arm/atmel_sam/samv71/soc.c +++ b/soc/arm/atmel_sam/samv71/soc.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -226,16 +228,19 @@ static ALWAYS_INLINE void clock_init(void) void z_arm_platform_init(void) { - if (IS_ENABLED(CONFIG_CACHE_MANAGEMENT) && IS_ENABLED(CONFIG_ICACHE)) { - SCB_EnableICache(); - } else { - SCB_DisableICache(); - } - if (IS_ENABLED(CONFIG_CACHE_MANAGEMENT) && IS_ENABLED(CONFIG_DCACHE)) { - SCB_EnableDCache(); - } else { - SCB_DisableDCache(); - } + /* + * DTCM is enabled by default at reset, therefore we have to disable + * it first to get the caches into a state where then the + * sys_cache*-functions can enable them, if requested by the + * configuration. + */ + SCB_DisableDCache(); + + /* + * Enable the caches only if configured to do so. + */ + sys_cache_instr_enable(); + sys_cache_data_enable(); /* * Set FWS (Flash Wait State) value before increasing Master Clock diff --git a/soc/arm/infineon_xmc/4xxx/Kconfig.series b/soc/arm/infineon_xmc/4xxx/Kconfig.series index 53312dfaf7b82ab..bfdbcc93091d82e 100644 --- a/soc/arm/infineon_xmc/4xxx/Kconfig.series +++ b/soc/arm/infineon_xmc/4xxx/Kconfig.series @@ -21,5 +21,6 @@ config SOC_SERIES_XMC_4XXX select HAS_XMCLIB_I2C select HAS_XMCLIB_CCU select HAS_XMCLIB_WDT + select HAS_XMCLIB_ETH help Enable support for XMC 4xxx MCU series diff --git a/soc/arm/infineon_xmc/4xxx/soc.c b/soc/arm/infineon_xmc/4xxx/soc.c index 0d4060568a33b9a..44e83a63c6f4dd9 100644 --- a/soc/arm/infineon_xmc/4xxx/soc.c +++ b/soc/arm/infineon_xmc/4xxx/soc.c @@ -37,6 +37,9 @@ void z_arm_platform_init(void) #endif #ifdef CONFIG_PWM_XMC4XXX_CCU8 | XMC_SCU_CLOCK_SLEEP_MODE_CONFIG_ENABLE_CCU +#endif +#ifdef CONFIG_ETH_XMC4XXX + | XMC_SCU_CLOCK_SLEEP_MODE_CONFIG_ENABLE_ETH #endif ); diff --git a/soc/arm/nordic_nrf/Kconfig.peripherals b/soc/arm/nordic_nrf/Kconfig.peripherals index 55f44ccbc21bf81..9e637f2661eef38 100644 --- a/soc/arm/nordic_nrf/Kconfig.peripherals +++ b/soc/arm/nordic_nrf/Kconfig.peripherals @@ -69,8 +69,23 @@ config HAS_HW_NRF_GPIO0 config HAS_HW_NRF_GPIO1 def_bool $(dt_nodelabel_enabled_with_compat,gpio1,$(DT_COMPAT_NORDIC_NRF_GPIO)) -config HAS_HW_NRF_GPIOTE - def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) +config HAS_HW_NRF_GPIOTE0 + def_bool $(dt_nodelabel_enabled_with_compat,gpiote0,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + +config HAS_HW_NRF_GPIOTE1 + def_bool $(dt_nodelabel_enabled_with_compat,gpiote1,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + +config HAS_HW_NRF_GPIOTE20 + def_bool $(dt_nodelabel_enabled_with_compat,gpiote20,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + +config HAS_HW_NRF_GPIOTE30 + def_bool $(dt_nodelabel_enabled_with_compat,gpiote30,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + +config HAS_HW_NRF_GPIOTE130 + def_bool $(dt_nodelabel_enabled_with_compat,gpiote130,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) + +config HAS_HW_NRF_GPIOTE131 + def_bool $(dt_nodelabel_enabled_with_compat,gpiote131,$(DT_COMPAT_NORDIC_NRF_GPIOTE)) config HAS_HW_NRF_I2S0 def_bool $(dt_nodelabel_enabled_with_compat,i2s0,$(DT_COMPAT_NORDIC_NRF_I2S)) diff --git a/soc/arm/nordic_nrf/common/soc_nrf_common.h b/soc/arm/nordic_nrf/common/soc_nrf_common.h index 4c00d7c0237cb83..1e5e603967b5643 100644 --- a/soc/arm/nordic_nrf/common/soc_nrf_common.h +++ b/soc/arm/nordic_nrf/common/soc_nrf_common.h @@ -149,6 +149,52 @@ (NRF_DT_GPIOS_TO_PSEL(node_id, prop)), \ (default_value)) +/** + * @brief Convert a devicetree GPIO phandle+specifier to GPIOTE instance number. + * + * Some of nRF SoCs may have more instances of GPIOTE. + * To handle this, we use the "gpiote-instance" property of the GPIO node. + * + * This macro converts a devicetree GPIO phandle array value + * "<&gpioX pin ...>" to a GPIOTE instance number. + * + * Examples: + * + * &gpiote0 { + * instance = <0>; + * }; + * + * &gpiote20 { + * instance = <20>; + * }; + * + * &gpio0 { + * gpiote-instance = <&gpiote0>; + * } + * + * &gpio1 { + * gpiote-instance = <&gpiote20>; + * } + * + * foo: my-node { + * tx-gpios = <&gpio0 4 ...>; + * rx-gpios = <&gpio0 5 ...>, <&gpio1 5 ...>; + * }; + * + * NRF_DT_GPIOTE_INST_BY_IDX(DT_NODELABEL(foo), tx_gpios, 0) // = 0 + * NRF_DT_GPIOTE_INST_BY_IDX(DT_NODELABEL(foo), rx_gpios, 1) // = 20 + */ +#define NRF_DT_GPIOTE_INST_BY_IDX(node_id, prop, idx) \ + DT_PROP(DT_PHANDLE(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx), \ + gpiote_instance), \ + instance) + +/** + * @brief Equivalent to NRF_DT_GPIOTE_INST_BY_IDX(node_id, prop, 0) + */ +#define NRF_DT_GPIOTE_INST(node_id, prop) \ + NRF_DT_GPIOTE_INST_BY_IDX(node_id, prop, 0) + /** * Error out the build if 'prop' is set on node 'node_id' and * DT_GPIO_CTLR(node_id, prop) is not an SoC GPIO controller, diff --git a/soc/arm/nordic_nrf/validate_base_addresses.c b/soc/arm/nordic_nrf/validate_base_addresses.c index 58aaa5a75134bca..ee440c3252c617e 100644 --- a/soc/arm/nordic_nrf/validate_base_addresses.c +++ b/soc/arm/nordic_nrf/validate_base_addresses.c @@ -16,6 +16,10 @@ #define NRF_CTRLAP NRF_CTRL_AP_PERI #endif +#if !defined(NRF_GPIOTE0) && defined(NRF_GPIOTE) +#define NRF_GPIOTE0 NRF_GPIOTE +#endif + #if !defined(NRF_I2S0) && defined(NRF_I2S) #define NRF_I2S0 NRF_I2S #endif @@ -141,6 +145,12 @@ CHECK_DT_REG(flash_controller, NRF_NVMC); CHECK_DT_REG(gpio0, NRF_P0); CHECK_DT_REG(gpio1, NRF_P1); CHECK_DT_REG(gpiote, NRF_GPIOTE); +CHECK_DT_REG(gpiote0, NRF_GPIOTE0); +CHECK_DT_REG(gpiote1, NRF_GPIOTE1); +CHECK_DT_REG(gpiote20, NRF_GPIOTE20); +CHECK_DT_REG(gpiote30, NRF_GPIOTE30); +CHECK_DT_REG(gpiote130, NRF_GPIOTE130); +CHECK_DT_REG(gpiote131, NRF_GPIOTE131); CHECK_I2C_REG(i2c0, 0); CHECK_I2C_REG(i2c1, 1); CHECK_DT_REG(i2c2, NRF_TWIM2); diff --git a/soc/arm/nxp_imx/rt/Kconfig.soc b/soc/arm/nxp_imx/rt/Kconfig.soc index 844fd27e9fbbae6..cbc00915046a32a 100644 --- a/soc/arm/nxp_imx/rt/Kconfig.soc +++ b/soc/arm/nxp_imx/rt/Kconfig.soc @@ -834,16 +834,4 @@ config SECOND_CORE_MCUX generated header specifying the VMA and LMA of each memory section to load -config IMXRT1XXX_CODE_CACHE - bool "Code cache" - default y - help - Enable Code cache at boot for IMXRT1xxx series - -config IMXRT1XXX_DATA_CACHE - bool "Data cache" - default y - help - Enable Data cache at boot for IMXRT1xxx series - endif # SOC_SERIES_IMX_RT diff --git a/soc/arm/nxp_imx/rt/soc_rt10xx.c b/soc/arm/nxp_imx/rt/soc_rt10xx.c index 01075ce358234b0..dd6e534be232cda 100644 --- a/soc/arm/nxp_imx/rt/soc_rt10xx.c +++ b/soc/arm/nxp_imx/rt/soc_rt10xx.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #ifdef CONFIG_NXP_IMX_RT_BOOT_HEADER #include @@ -318,23 +319,8 @@ void imxrt_audio_codec_pll_init(uint32_t clock_name, uint32_t clk_src, static int imxrt_init(void) { -#ifndef CONFIG_IMXRT1XXX_CODE_CACHE - /* SystemInit enables code cache, disable it here */ - SCB_DisableICache(); -#else - /* z_arm_init_arch_hw_at_boot() disables code cache if CONFIG_ARCH_CACHE is enabled, - * enable it here. - */ - SCB_EnableICache(); -#endif - - if (IS_ENABLED(CONFIG_IMXRT1XXX_DATA_CACHE)) { - if ((SCB->CCR & SCB_CCR_DC_Msk) == 0) { - SCB_EnableDCache(); - } - } else { - SCB_DisableDCache(); - } + sys_cache_instr_enable(); + sys_cache_data_enable(); /* Initialize system clock */ clock_init(); diff --git a/soc/arm/nxp_imx/rt/soc_rt11xx.c b/soc/arm/nxp_imx/rt/soc_rt11xx.c index 9c38f3e796318e3..3adedde8d38c51f 100644 --- a/soc/arm/nxp_imx/rt/soc_rt11xx.c +++ b/soc/arm/nxp_imx/rt/soc_rt11xx.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -673,23 +674,8 @@ static int imxrt_init(void) #if defined(CONFIG_SOC_MIMXRT1176_CM7) || defined(CONFIG_SOC_MIMXRT1166_CM7) -#ifndef CONFIG_IMXRT1XXX_CODE_CACHE - /* SystemInit enables code cache, disable it here */ - SCB_DisableICache(); -#else - /* z_arm_init_arch_hw_at_boot() disables code cache if CONFIG_ARCH_CACHE is enabled, - * enable it here. - */ - SCB_EnableICache(); -#endif - - if (IS_ENABLED(CONFIG_IMXRT1XXX_DATA_CACHE)) { - if ((SCB->CCR & SCB_CCR_DC_Msk) == 0) { - SCB_EnableDCache(); - } - } else { - SCB_DisableDCache(); - } + sys_cache_instr_enable(); + sys_cache_data_enable(); #endif /* Initialize system clock */ diff --git a/soc/arm/nxp_imx/rt5xx/Kconfig.soc b/soc/arm/nxp_imx/rt5xx/Kconfig.soc index 2c82c533de99813..35b86c2e90358e3 100644 --- a/soc/arm/nxp_imx/rt5xx/Kconfig.soc +++ b/soc/arm/nxp_imx/rt5xx/Kconfig.soc @@ -1,6 +1,6 @@ # i.MX RT5XX Series -# Copyright (c) 2022, NXP +# Copyright 2022-2023, NXP # SPDX-License-Identifier: Apache-2.0 choice @@ -129,4 +129,28 @@ config IMXRT5XX_CODE_CACHE Enable code cache for FlexSPI region at boot. If this Kconfig is cleared, the CACHE64 controller will be disabled during SOC init +choice FLEXCOMM0_CLK_SRC + prompt "Clock source for Flexcomm0" + default FLEXCOMM0_CLK_SRC_FRG + +config FLEXCOMM0_CLK_SRC_FRG + bool "FRG is source of Flexcomm0 clock" + +config FLEXCOMM0_CLK_SRC_FRO + bool "FRO_DIV4 is source of Flexcomm0 clock" + +endchoice + +choice MIPI_DPHY_CLK_SRC + prompt "Clock source for MIPI DPHY" + default MIPI_DPHY_CLK_SRC_AUX1_PLL + +config MIPI_DPHY_CLK_SRC_AUX1_PLL + bool "AUX1_PLL is source of MIPI_DPHY clock" + +config MIPI_DPHY_CLK_SRC_FRO + bool "FRO 192/96M is source of MIPI_DPHY clock" + +endchoice + endif # SOC_SERIES_IMX_RT5XX diff --git a/soc/arm/nxp_imx/rt5xx/soc.c b/soc/arm/nxp_imx/rt5xx/soc.c index d834d3e55bc05e9..85e4a9004134461 100644 --- a/soc/arm/nxp_imx/rt5xx/soc.c +++ b/soc/arm/nxp_imx/rt5xx/soc.c @@ -281,8 +281,12 @@ void __weak rt5xx_clock_init(void) /* Switch SYSTICK_CLK to MAIN_CLK_DIV */ CLOCK_AttachClk(kMAIN_CLK_DIV_to_SYSTICK_CLK); #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_usart, okay) - /* Switch FLEXCOMM0 to FRG */ - CLOCK_AttachClk(kFRG_to_FLEXCOMM0); + #ifdef CONFIG_FLEXCOMM0_CLK_SRC_FRG + /* Switch FLEXCOMM0 to FRG */ + CLOCK_AttachClk(kFRG_to_FLEXCOMM0); + #elif defined(CONFIG_FLEXCOMM0_CLK_SRC_FRO) + CLOCK_AttachClk(kFRO_DIV4_to_FLEXCOMM0); + #endif #endif #if CONFIG_USB_DC_NXP_LPCIP3511 usb_device_clock_init(); @@ -458,12 +462,21 @@ void __weak imxrt_pre_init_display_interface(void) * We set the divider of the PFD3 output of the SYSPLL, which has a * fixed multiplied of 18, and use this output frequency for the DPHY. */ + +#ifdef CONFIG_MIPI_DPHY_CLK_SRC_AUX1_PLL + /* Note: AUX1 PLL clock is system pll clock * 18 / pfd. + * system pll clock is configured at 528MHz by default. + */ CLOCK_AttachClk(kAUX1_PLL_to_MIPI_DPHY_CLK); CLOCK_InitSysPfd(kCLOCK_Pfd3, ((CLOCK_GetSysPllFreq() * 18ull) / ((unsigned long long)(DT_PROP(DT_NODELABEL(mipi_dsi), phy_clock))))); CLOCK_SetClkDiv(kCLOCK_DivDphyClk, 1); - +#elif defined(CONFIG_MIPI_DPHY_CLK_SRC_FRO) + CLOCK_AttachClk(kFRO_DIV1_to_MIPI_DPHY_CLK); + CLOCK_SetClkDiv(kCLOCK_DivDphyClk, + (CLK_FRO_CLK / DT_PROP(DT_NODELABEL(mipi_dsi), phy_clock))); +#endif /* Clear DSI control reset (Note that DPHY reset is cleared later)*/ RESET_ClearPeripheralReset(kMIPI_DSI_CTRL_RST_SHIFT_RSTn); } diff --git a/soc/arm/nxp_kinetis/kv5x/Kconfig.soc b/soc/arm/nxp_kinetis/kv5x/Kconfig.soc index 3a9a6d3adf2487a..dd69ca523b0b410 100644 --- a/soc/arm/nxp_kinetis/kv5x/Kconfig.soc +++ b/soc/arm/nxp_kinetis/kv5x/Kconfig.soc @@ -57,12 +57,4 @@ config SOC_PART_NUMBER_KINETIS_KV5X number selection choice defines the default value for this string. -config KINETIS_KV5X_ENABLE_CODE_CACHE - bool "Code cache" - default y - -config KINETIS_KV5X_ENABLE_DATA_CACHE - bool "Data cache" - default y - endif # SOC_SERIES_KINETIS_KV5X diff --git a/soc/arm/nxp_kinetis/kv5x/soc.c b/soc/arm/nxp_kinetis/kv5x/soc.c index 4c566dadcd05513..59b77f1c1724913 100644 --- a/soc/arm/nxp_kinetis/kv5x/soc.c +++ b/soc/arm/nxp_kinetis/kv5x/soc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -90,14 +91,8 @@ static int kv5x_init(void) /* Initialize system clocks and PLL */ clk_init(); -#ifndef CONFIG_KINETIS_KV5X_ENABLE_CODE_CACHE - /* SystemInit will have enabled the code cache. Disable it here */ - SCB_DisableICache(); -#endif -#ifndef CONFIG_KINETIS_KV5X_ENABLE_DATA_CACHE - /* SystemInit will have enabled the data cache. Disable it here */ - SCB_DisableDCache(); -#endif + sys_cache_instr_enable(); + sys_cache_data_enable(); return 0; } diff --git a/soc/arm/nxp_s32/s32k1/Kconfig.series b/soc/arm/nxp_s32/s32k1/Kconfig.series index 9b6f008650905fb..12d74205412a4ae 100644 --- a/soc/arm/nxp_s32/s32k1/Kconfig.series +++ b/soc/arm/nxp_s32/s32k1/Kconfig.series @@ -16,5 +16,7 @@ config SOC_SERIES_S32K1XX select HAS_MCUX_LPUART select HAS_MCUX_LPI2C select HAS_MCUX_LPSPI + select HAS_MCUX_FTM + select HAS_MCUX_FLEXCAN help Enable support for NXP S32K1XX MCU series. diff --git a/soc/arm/nxp_s32/s32k3/soc.c b/soc/arm/nxp_s32/s32k3/soc.c index 5db4204a89ca5b3..be822677189e614 100644 --- a/soc/arm/nxp_s32/s32k3/soc.c +++ b/soc/arm/nxp_s32/s32k3/soc.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -50,13 +51,8 @@ const struct ivt ivt_header __attribute__((section(".ivt_header"))) = { static int soc_init(void) { - SCB_EnableICache(); - - if (IS_ENABLED(CONFIG_DCACHE)) { - if (!(SCB->CCR & SCB_CCR_DC_Msk)) { - SCB_EnableDCache(); - } - } + sys_cache_instr_enable(); + sys_cache_data_enable(); OsIf_Init(NULL); diff --git a/soc/arm/st_stm32/stm32f4/Kconfig.defconfig.series b/soc/arm/st_stm32/stm32f4/Kconfig.defconfig.series index 067dcfc003f36de..63725609480192f 100644 --- a/soc/arm/st_stm32/stm32f4/Kconfig.defconfig.series +++ b/soc/arm/st_stm32/stm32f4/Kconfig.defconfig.series @@ -17,8 +17,17 @@ config TASK_WDT_HW_FALLBACK_DELAY depends on TASK_WDT_HW_FALLBACK default 200 -config PM - select COUNTER - select COUNTER_RTC_STM32_SUBSECONDS if DT_HAS_ST_STM32_RTC_ENABLED +if PM + +config COUNTER + default y + +config COUNTER_RTC_STM32_SUBSECONDS + default y if DT_HAS_ST_STM32_RTC_ENABLED + +config IDLE_STACK_SIZE + default 512 + +endif # PM endif # SOC_SERIES_STM32F4X diff --git a/soc/arm/st_stm32/stm32f7/soc.c b/soc/arm/st_stm32/stm32f7/soc.c index 19941c9cee061ff..4a9cc72a78dc85e 100644 --- a/soc/arm/st_stm32/stm32f7/soc.c +++ b/soc/arm/st_stm32/stm32f7/soc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -30,13 +31,8 @@ static int st_stm32f7_init(void) /* Enable ART Flash cache accelerator */ LL_FLASH_EnableART(); - if (IS_ENABLED(CONFIG_ICACHE)) { - SCB_EnableICache(); - } - - if (IS_ENABLED(CONFIG_DCACHE)) { - SCB_EnableDCache(); - } + sys_cache_instr_enable(); + sys_cache_data_enable(); /* Update CMSIS SystemCoreClock variable (HCLK) */ /* At reset, system core clock is set to 16 MHz from HSI */ diff --git a/soc/arm/st_stm32/stm32h7/soc_m7.c b/soc/arm/st_stm32/stm32h7/soc_m7.c index 7ee62921c41c600..39c1d917c34942e 100644 --- a/soc/arm/st_stm32/stm32h7/soc_m7.c +++ b/soc/arm/st_stm32/stm32h7/soc_m7.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -54,13 +55,8 @@ static int stm32h7_m4_wakeup(void) */ static int stm32h7_init(void) { - if (IS_ENABLED(CONFIG_ICACHE)) { - SCB_EnableICache(); - } - - if (IS_ENABLED(CONFIG_DCACHE)) { - SCB_EnableDCache(); - } + sys_cache_instr_enable(); + sys_cache_data_enable(); /* Update CMSIS SystemCoreClock variable (HCLK) */ /* At reset, system core clock is set to 64 MHz from HSI */ diff --git a/soc/arm/ti_simplelink/cc32xx/Kconfig.defconfig.cc3220sf b/soc/arm/ti_simplelink/cc32xx/Kconfig.defconfig.cc3220sf index e082df05a80d295..461802f2155ad4d 100644 --- a/soc/arm/ti_simplelink/cc32xx/Kconfig.defconfig.cc3220sf +++ b/soc/arm/ti_simplelink/cc32xx/Kconfig.defconfig.cc3220sf @@ -19,10 +19,6 @@ config ROM_START_OFFSET default 0x800 if XIP default 0x0 if !XIP -# Override the setting in misc/Kconfig to allow full use of SRAM: -config BOOTLOADER_SRAM_SIZE - default 0 if !XIP - if !XIP config FLASH_SIZE default 0 diff --git a/soc/arm/ti_simplelink/cc32xx/Kconfig.defconfig.cc3235sf b/soc/arm/ti_simplelink/cc32xx/Kconfig.defconfig.cc3235sf index 86c881a40f9acc7..37852a154a015b8 100644 --- a/soc/arm/ti_simplelink/cc32xx/Kconfig.defconfig.cc3235sf +++ b/soc/arm/ti_simplelink/cc32xx/Kconfig.defconfig.cc3235sf @@ -20,10 +20,6 @@ config ROM_START_OFFSET default 0x800 if XIP default 0x0 if !XIP -# Override the setting in misc/Kconfig to allow full use of SRAM: -config BOOTLOADER_SRAM_SIZE - default 0 if !XIP - if !XIP config FLASH_SIZE default 0 diff --git a/soc/riscv/CMakeLists.txt b/soc/riscv/CMakeLists.txt index b826da926caf128..79d115704b2943c 100644 --- a/soc/riscv/CMakeLists.txt +++ b/soc/riscv/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +add_subdirectory(common) + if(SOC_FAMILY) add_subdirectory(${SOC_FAMILY}) else() diff --git a/soc/riscv/andes_v5/CMakeLists.txt b/soc/riscv/andes_v5/CMakeLists.txt new file mode 100644 index 000000000000000..69b2926358e5cf8 --- /dev/null +++ b/soc/riscv/andes_v5/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(${SOC_SERIES}) diff --git a/soc/riscv/andes_v5/Kconfig b/soc/riscv/andes_v5/Kconfig new file mode 100644 index 000000000000000..f3c78ab7f813c6b --- /dev/null +++ b/soc/riscv/andes_v5/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_ANDES_V5 + bool + +if SOC_FAMILY_ANDES_V5 + +config SOC_FAMILY + string + default "andes_v5" + +source "soc/riscv/andes_v5/*/Kconfig.soc" + +endif # SOC_FAMILY_ANDES_V5 diff --git a/soc/riscv/andes_v5/Kconfig.defconfig b/soc/riscv/andes_v5/Kconfig.defconfig new file mode 100644 index 000000000000000..6213f28d2cb38e7 --- /dev/null +++ b/soc/riscv/andes_v5/Kconfig.defconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/andes_v5/*/Kconfig.defconfig.series" diff --git a/soc/riscv/andes_v5/Kconfig.soc b/soc/riscv/andes_v5/Kconfig.soc new file mode 100644 index 000000000000000..9efb478193444cc --- /dev/null +++ b/soc/riscv/andes_v5/Kconfig.soc @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/andes_v5/*/Kconfig.series" diff --git a/soc/riscv/riscv-privileged/andes_v5/CMakeLists.txt b/soc/riscv/andes_v5/ae350/CMakeLists.txt similarity index 82% rename from soc/riscv/riscv-privileged/andes_v5/CMakeLists.txt rename to soc/riscv/andes_v5/ae350/CMakeLists.txt index 212683123474f5d..b8eac026dfbb4eb 100644 --- a/soc/riscv/riscv-privileged/andes_v5/CMakeLists.txt +++ b/soc/riscv/andes_v5/ae350/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 -zephyr_include_directories(${CONFIG_SOC}) +zephyr_include_directories(.) zephyr_sources( start.S @@ -24,6 +24,6 @@ if(CONFIG_SOC_ANDES_V5_EXECIT) zephyr_ld_options(-Wl,--mexecit) endif() -if(CONFIG_SOC_RISCV_ANDES_AE350) - set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/ae350/linker.ld CACHE INTERNAL "") +if(CONFIG_SOC_ANDES_AE350) + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") endif() diff --git a/soc/riscv/riscv-privileged/andes_v5/Kconfig.defconfig.ae350 b/soc/riscv/andes_v5/ae350/Kconfig.defconfig.ae350 similarity index 88% rename from soc/riscv/riscv-privileged/andes_v5/Kconfig.defconfig.ae350 rename to soc/riscv/andes_v5/ae350/Kconfig.defconfig.ae350 index 5d652057a38b7ce..fee73684b7150c2 100644 --- a/soc/riscv/riscv-privileged/andes_v5/Kconfig.defconfig.ae350 +++ b/soc/riscv/andes_v5/ae350/Kconfig.defconfig.ae350 @@ -1,7 +1,7 @@ # Copyright (c) 2021 Andes Technology Corporation # SPDX-License-Identifier: Apache-2.0 -if SOC_RISCV_ANDES_AE350 +if SOC_ANDES_AE350 config SOC default "ae350" @@ -25,4 +25,4 @@ config MP_MAX_NUM_CPUS default 1 range 1 8 -endif # SOC_RISCV_ANDES_AE350 +endif # SOC_ANDES_AE350 diff --git a/soc/riscv/riscv-privileged/andes_v5/Kconfig.defconfig.series b/soc/riscv/andes_v5/ae350/Kconfig.defconfig.series similarity index 83% rename from soc/riscv/riscv-privileged/andes_v5/Kconfig.defconfig.series rename to soc/riscv/andes_v5/ae350/Kconfig.defconfig.series index c6436807825f55c..7bd679e5f459e18 100644 --- a/soc/riscv/riscv-privileged/andes_v5/Kconfig.defconfig.series +++ b/soc/riscv/andes_v5/ae350/Kconfig.defconfig.series @@ -1,15 +1,15 @@ # Copyright (c) 2021 Andes Technology Corporation # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_RISCV_ANDES_V5 +if SOC_SERIES_ANDES_AE350 # Kconfig picks the first default with a satisfied condition. # SoC defaults should be parsed before SoC Series defaults, because SoCs usually # overrides SoC Series values. -source "soc/riscv/riscv-privileged/andes_v5/Kconfig.defconfig.ae*" +source "soc/riscv/andes_v5/ae350/Kconfig.defconfig.ae*" config SOC_SERIES - default "andes_v5" + default "ae350" config SYS_CLOCK_HW_CYCLES_PER_SEC default 60000000 @@ -45,4 +45,4 @@ config MAX_IRQ_PER_AGGREGATOR config NUM_IRQS default 64 -endif # SOC_SERIES_RISCV_ANDES_V5 +endif # SOC_SERIES_ANDES_AE350 diff --git a/soc/riscv/andes_v5/ae350/Kconfig.series b/soc/riscv/andes_v5/ae350/Kconfig.series new file mode 100644 index 000000000000000..ebf68f7a3aa3188 --- /dev/null +++ b/soc/riscv/andes_v5/ae350/Kconfig.series @@ -0,0 +1,10 @@ +# Copyright (c) 2021 Andes Technology Corporation +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_ANDES_AE350 + bool "Andes V5 AE350 SoC Series Implementation" + select RISCV + select RISCV_PRIVILEGED + select SOC_FAMILY_ANDES_V5 + help + Enable support for Andes V5 AE350 SoC Series diff --git a/soc/riscv/riscv-privileged/andes_v5/Kconfig.soc b/soc/riscv/andes_v5/ae350/Kconfig.soc similarity index 95% rename from soc/riscv/riscv-privileged/andes_v5/Kconfig.soc rename to soc/riscv/andes_v5/ae350/Kconfig.soc index 19f215e2c5ac766..1731cc08f51c98f 100644 --- a/soc/riscv/riscv-privileged/andes_v5/Kconfig.soc +++ b/soc/riscv/andes_v5/ae350/Kconfig.soc @@ -3,9 +3,9 @@ choice prompt "Andes V5 SoC Selection" -depends on SOC_SERIES_RISCV_ANDES_V5 +depends on SOC_SERIES_ANDES_AE350 -config SOC_RISCV_ANDES_AE350 +config SOC_ANDES_AE350 bool "Andes AE350 SoC implementation" select ATOMIC_OPERATIONS_BUILTIN select INCLUDE_RESET_VECTOR @@ -18,7 +18,7 @@ config SOC_RISCV_ANDES_AE350 endchoice -if SOC_SERIES_RISCV_ANDES_V5 +if SOC_SERIES_ANDES_AE350 choice prompt "Base CPU ISA options" @@ -121,4 +121,4 @@ config SOC_ANDES_V5_IOCP between cache and external non-caching master, such as DMA controller. -endif # SOC_SERIES_RISCV_ANDES_V5 +endif # SOC_SERIES_ANDES_AE350 diff --git a/soc/riscv/riscv-privileged/andes_v5/common_linker/execit.ld b/soc/riscv/andes_v5/ae350/common_linker/execit.ld similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/common_linker/execit.ld rename to soc/riscv/andes_v5/ae350/common_linker/execit.ld diff --git a/soc/riscv/riscv-privileged/andes_v5/common_linker/init.ld b/soc/riscv/andes_v5/ae350/common_linker/init.ld similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/common_linker/init.ld rename to soc/riscv/andes_v5/ae350/common_linker/init.ld diff --git a/soc/riscv/riscv-privileged/andes_v5/common_linker/ram_start_nonzero.ld b/soc/riscv/andes_v5/ae350/common_linker/ram_start_nonzero.ld similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/common_linker/ram_start_nonzero.ld rename to soc/riscv/andes_v5/ae350/common_linker/ram_start_nonzero.ld diff --git a/soc/riscv/riscv-privileged/andes_v5/l2_cache.c b/soc/riscv/andes_v5/ae350/l2_cache.c similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/l2_cache.c rename to soc/riscv/andes_v5/ae350/l2_cache.c diff --git a/soc/riscv/riscv-privileged/andes_v5/ae350/linker.ld b/soc/riscv/andes_v5/ae350/linker.ld similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/ae350/linker.ld rename to soc/riscv/andes_v5/ae350/linker.ld diff --git a/soc/riscv/riscv-privileged/andes_v5/pma.c b/soc/riscv/andes_v5/ae350/pma.c similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/pma.c rename to soc/riscv/andes_v5/ae350/pma.c diff --git a/soc/riscv/riscv-privileged/andes_v5/ae350/soc.h b/soc/riscv/andes_v5/ae350/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/ae350/soc.h rename to soc/riscv/andes_v5/ae350/soc.h diff --git a/soc/riscv/riscv-privileged/andes_v5/soc_context.h b/soc/riscv/andes_v5/ae350/soc_context.h similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/soc_context.h rename to soc/riscv/andes_v5/ae350/soc_context.h diff --git a/soc/riscv/riscv-privileged/andes_v5/soc_irq.S b/soc/riscv/andes_v5/ae350/soc_irq.S similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/soc_irq.S rename to soc/riscv/andes_v5/ae350/soc_irq.S diff --git a/soc/riscv/riscv-privileged/andes_v5/soc_offsets.h b/soc/riscv/andes_v5/ae350/soc_offsets.h similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/soc_offsets.h rename to soc/riscv/andes_v5/ae350/soc_offsets.h diff --git a/soc/riscv/riscv-privileged/andes_v5/soc_v5.h b/soc/riscv/andes_v5/ae350/soc_v5.h similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/soc_v5.h rename to soc/riscv/andes_v5/ae350/soc_v5.h diff --git a/soc/riscv/riscv-privileged/andes_v5/start.S b/soc/riscv/andes_v5/ae350/start.S similarity index 100% rename from soc/riscv/riscv-privileged/andes_v5/start.S rename to soc/riscv/andes_v5/ae350/start.S diff --git a/soc/riscv/common/CMakeLists.txt b/soc/riscv/common/CMakeLists.txt new file mode 100644 index 000000000000000..91ef5c975b919aa --- /dev/null +++ b/soc/riscv/common/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory_ifdef(CONFIG_RISCV_PRIVILEGED riscv-privileged) diff --git a/soc/riscv/common/Kconfig b/soc/riscv/common/Kconfig new file mode 100644 index 000000000000000..91f2c5cf80a4346 --- /dev/null +++ b/soc/riscv/common/Kconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# +source "soc/riscv/common/riscv-privileged/Kconfig" diff --git a/soc/riscv/riscv-privileged/common/CMakeLists.txt b/soc/riscv/common/riscv-privileged/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/common/CMakeLists.txt rename to soc/riscv/common/riscv-privileged/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/Kconfig b/soc/riscv/common/riscv-privileged/Kconfig similarity index 63% rename from soc/riscv/riscv-privileged/Kconfig rename to soc/riscv/common/riscv-privileged/Kconfig index abbeeac242bcf16..a4a8da0bf1f83d5 100644 --- a/soc/riscv/riscv-privileged/Kconfig +++ b/soc/riscv/common/riscv-privileged/Kconfig @@ -4,35 +4,20 @@ # Copyright (c) 2017 Jean-Paul Etienne # SPDX-License-Identifier: Apache-2.0 -config SOC_FAMILY_RISCV_PRIVILEGE - bool - select DEPRECATED - -config SOC_FAMILY_RISCV_PRIVILEGED - bool - select ARCH_HAS_RAMFUNC_SUPPORT if XIP - -config SOC_FAMILY - string - default "riscv-privileged" - depends on SOC_FAMILY_RISCV_PRIVILEGED - config RISCV_HAS_PLIC bool "Does the SOC provide support for a Platform Level Interrupt Controller (PLIC)" - depends on SOC_FAMILY_RISCV_PRIVILEGED + depends on RISCV_PRIVILEGED help Does the SOC provide support for a Platform Level Interrupt Controller (PLIC). config RISCV_HAS_CLIC bool "Does the SOC provide support for a Core-Local Interrupt Controller (CLIC)" - depends on SOC_FAMILY_RISCV_PRIVILEGED + depends on RISCV_PRIVILEGED help Does the SOC provide support for a Core-Local Interrupt Controller (CLIC). config RISCV_VECTORED_MODE bool "Should the SOC use vectored mode" - depends on SOC_FAMILY_RISCV_PRIVILEGED + depends on RISCV_PRIVILEGED help Should the SOC use vectored mode. - -source "soc/riscv/riscv-privileged/*/Kconfig.soc" diff --git a/soc/riscv/riscv-privileged/common/idle.c b/soc/riscv/common/riscv-privileged/idle.c similarity index 100% rename from soc/riscv/riscv-privileged/common/idle.c rename to soc/riscv/common/riscv-privileged/idle.c diff --git a/soc/riscv/riscv-privileged/common/soc_common.h b/soc/riscv/common/riscv-privileged/soc_common.h similarity index 100% rename from soc/riscv/riscv-privileged/common/soc_common.h rename to soc/riscv/common/riscv-privileged/soc_common.h diff --git a/soc/riscv/riscv-privileged/common/soc_common_irq.c b/soc/riscv/common/riscv-privileged/soc_common_irq.c similarity index 100% rename from soc/riscv/riscv-privileged/common/soc_common_irq.c rename to soc/riscv/common/riscv-privileged/soc_common_irq.c diff --git a/soc/riscv/riscv-privileged/common/soc_irq.S b/soc/riscv/common/riscv-privileged/soc_irq.S similarity index 100% rename from soc/riscv/riscv-privileged/common/soc_irq.S rename to soc/riscv/common/riscv-privileged/soc_irq.S diff --git a/soc/riscv/riscv-privileged/common/vector.S b/soc/riscv/common/riscv-privileged/vector.S similarity index 100% rename from soc/riscv/riscv-privileged/common/vector.S rename to soc/riscv/common/riscv-privileged/vector.S diff --git a/soc/riscv/riscv-privileged/efinix-sapphire/CMakeLists.txt b/soc/riscv/efinix_sapphire/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/efinix-sapphire/CMakeLists.txt rename to soc/riscv/efinix_sapphire/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/efinix-sapphire/Kconfig.defconfig.series b/soc/riscv/efinix_sapphire/Kconfig.defconfig similarity index 75% rename from soc/riscv/riscv-privileged/efinix-sapphire/Kconfig.defconfig.series rename to soc/riscv/efinix_sapphire/Kconfig.defconfig index e2f31e91a7b250e..7018c0f11fb5f14 100644 --- a/soc/riscv/riscv-privileged/efinix-sapphire/Kconfig.defconfig.series +++ b/soc/riscv/efinix_sapphire/Kconfig.defconfig @@ -1,10 +1,10 @@ # Copyright (c) 2023 Efinix Inc. # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_EFINIX_SAPPHIRE +if SOC_EFINIX_SAPPHIRE -config SOC_SERIES - default "efinix-sapphire" +config SOC + default "efinix_sapphire" config SYS_CLOCK_HW_CYCLES_PER_SEC default 100000000 @@ -28,4 +28,4 @@ config NUM_IRQS config 2ND_LVL_INTR_00_OFFSET default 11 -endif # SOC_SERIES_EFINIX_SAPPHIRE +endif # SOC_EFINIX_SAPPHIRE diff --git a/soc/riscv/riscv-privileged/efinix-sapphire/Kconfig.soc b/soc/riscv/efinix_sapphire/Kconfig.soc similarity index 72% rename from soc/riscv/riscv-privileged/efinix-sapphire/Kconfig.soc rename to soc/riscv/efinix_sapphire/Kconfig.soc index dba8491b8bdab3a..bf57d9cc5411a5f 100644 --- a/soc/riscv/riscv-privileged/efinix-sapphire/Kconfig.soc +++ b/soc/riscv/efinix_sapphire/Kconfig.soc @@ -1,11 +1,7 @@ # Copyright (c) 2023 Efinix Inc. # SPDX-License-Identifier: Apache-2.0 -choice - prompt "Efinix SoC selection" - depends on SOC_SERIES_EFINIX_SAPPHIRE - -config SOC_RISCV32_EFINIX_SAPPHIRE +config SOC_EFINIX_SAPPHIRE bool "Efinix Sapphire VexRiscv system implementation" select ATOMIC_OPERATIONS_BUILTIN select INCLUDE_RESET_VECTOR @@ -14,5 +10,5 @@ config SOC_RISCV32_EFINIX_SAPPHIRE select RISCV_ISA_EXT_A select RISCV_ISA_EXT_ZICSR select RISCV_ISA_EXT_ZIFENCEI - -endchoice + select RISCV + select RISCV_PRIVILEGED diff --git a/soc/riscv/riscv-privileged/efinix-sapphire/soc.h b/soc/riscv/efinix_sapphire/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/efinix-sapphire/soc.h rename to soc/riscv/efinix_sapphire/soc.h diff --git a/soc/riscv/espressif_esp32/esp32c3/default.ld b/soc/riscv/espressif_esp32/esp32c3/default.ld index 0884e3d7d3aba1f..65984b4fd7b2699 100644 --- a/soc/riscv/espressif_esp32/esp32c3/default.ld +++ b/soc/riscv/espressif_esp32/esp32c3/default.ld @@ -142,8 +142,8 @@ SECTIONS #include . = ALIGN(4); - *(EXCLUDE_FILE (*libarch__xtensa__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libdrivers__flash.a:esp32_mp.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__flash.a:flash_esp32.* *libdrivers__serial.a:uart_esp32.* *libzephyr.a:spi_flash_rom_patch.*) .rodata) - *(EXCLUDE_FILE (*libarch__xtensa__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libdrivers__flash.a:esp32_mp.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__flash.a:flash_esp32.* *libdrivers__serial.a:uart_esp32.* *libzephyr.a:spi_flash_rom_patch.*) .rodata.*) + *(EXCLUDE_FILE (*libarch__riscv__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libdrivers__flash.a:esp32_mp.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__flash.a:flash_esp32.* *libdrivers__serial.a:uart_esp32.* *libzephyr.a:spi_flash_rom_patch.*) .rodata) + *(EXCLUDE_FILE (*libarch__riscv__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libdrivers__flash.a:esp32_mp.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__flash.a:flash_esp32.* *libdrivers__serial.a:uart_esp32.* *libzephyr.a:spi_flash_rom_patch.*) .rodata.*) *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) @@ -175,18 +175,12 @@ SECTIONS *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) *(.srodata) *(.srodata.*) *(.rodata) *(.rodata.*) *(.rodata_wlog) *(.rodata_wlog*) - _thread_local_end = ABSOLUTE(.); . = ALIGN(4); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) @@ -197,6 +191,7 @@ SECTIONS #include #include #include + #include #include /* Create an explicit section at the end of all the data that shall be mapped into drom. @@ -233,6 +228,7 @@ SECTIONS *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) *libesp32.a:panic.*(.literal .text .literal.* .text.*) *librtc.a:(.literal .text .literal.* .text.*) + *libarch__riscv__core.a:(.literal .text .literal.* .text.*) *libsubsys__net__l2__ethernet.a:(.literal .text .literal.* .text.*) *libsubsys__net__lib__config.a:(.literal .text .literal.* .text.*) *libsubsys__net__ip.a:(.literal .text .literal.* .text.*) diff --git a/soc/riscv/gd_gd32/CMakeLists.txt b/soc/riscv/gd_gd32/CMakeLists.txt new file mode 100644 index 000000000000000..69b2926358e5cf8 --- /dev/null +++ b/soc/riscv/gd_gd32/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(${SOC_SERIES}) diff --git a/soc/riscv/gd_gd32/Kconfig b/soc/riscv/gd_gd32/Kconfig new file mode 100644 index 000000000000000..46f2dd0b1d6b01b --- /dev/null +++ b/soc/riscv/gd_gd32/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_GD32 + bool + +if SOC_FAMILY_GD32 + +config SOC_FAMILY + string + default "gd_gd32" + +source "soc/riscv/gd_gd32/*/Kconfig.soc" + +endif # SOC_FAMILY_GIGADEVICE_GD32 diff --git a/soc/riscv/gd_gd32/Kconfig.defconfig b/soc/riscv/gd_gd32/Kconfig.defconfig new file mode 100644 index 000000000000000..2be284db7eac4cf --- /dev/null +++ b/soc/riscv/gd_gd32/Kconfig.defconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/gd_gd32/*/Kconfig.defconfig.series" diff --git a/soc/riscv/gd_gd32/Kconfig.soc b/soc/riscv/gd_gd32/Kconfig.soc new file mode 100644 index 000000000000000..09d7d5d627ea5f3 --- /dev/null +++ b/soc/riscv/gd_gd32/Kconfig.soc @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/gd_gd32/*/Kconfig.series" diff --git a/soc/riscv/riscv-privileged/gd32vf103/CMakeLists.txt b/soc/riscv/gd_gd32/gd32vf103/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/gd32vf103/CMakeLists.txt rename to soc/riscv/gd_gd32/gd32vf103/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/gd32vf103/Kconfig.defconfig.gd32vf103 b/soc/riscv/gd_gd32/gd32vf103/Kconfig.defconfig.gd32vf103 similarity index 100% rename from soc/riscv/riscv-privileged/gd32vf103/Kconfig.defconfig.gd32vf103 rename to soc/riscv/gd_gd32/gd32vf103/Kconfig.defconfig.gd32vf103 diff --git a/soc/riscv/riscv-privileged/gd32vf103/Kconfig.defconfig.series b/soc/riscv/gd_gd32/gd32vf103/Kconfig.defconfig.series similarity index 72% rename from soc/riscv/riscv-privileged/gd32vf103/Kconfig.defconfig.series rename to soc/riscv/gd_gd32/gd32vf103/Kconfig.defconfig.series index 061b53b2514ead7..17ab7a87c392f0c 100644 --- a/soc/riscv/riscv-privileged/gd32vf103/Kconfig.defconfig.series +++ b/soc/riscv/gd_gd32/gd32vf103/Kconfig.defconfig.series @@ -3,7 +3,7 @@ if SOC_SERIES_GD32VF103 -source "soc/riscv/riscv-privileged/gd32vf103/Kconfig.defconfig.gd32vf103*" +source "soc/riscv/gd_gd32/gd32vf103/Kconfig.defconfig.gd32vf103*" config SOC_SERIES default "gd32vf103" diff --git a/soc/riscv/riscv-privileged/gd32vf103/Kconfig.series b/soc/riscv/gd_gd32/gd32vf103/Kconfig.series similarity index 90% rename from soc/riscv/riscv-privileged/gd32vf103/Kconfig.series rename to soc/riscv/gd_gd32/gd32vf103/Kconfig.series index 3922bf19bdda08d..e50567e07980a49 100644 --- a/soc/riscv/riscv-privileged/gd32vf103/Kconfig.series +++ b/soc/riscv/gd_gd32/gd32vf103/Kconfig.series @@ -6,7 +6,7 @@ config SOC_SERIES_GD32VF103 bool "GigaDevice GD32VF103 series SoC implementation" select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED + select RISCV_PRIVILEGED select ATOMIC_OPERATIONS_C select INCLUDE_RESET_VECTOR select BUILD_OUTPUT_HEX @@ -15,6 +15,6 @@ config SOC_SERIES_GD32VF103 select GD32_HAS_IRC_40K select HAS_GD32_HAL select RISCV_HAS_CLIC - + select SOC_FAMILY_GD32 help Enable support for GigaDevice GD32VF1 series SoC diff --git a/soc/riscv/riscv-privileged/gd32vf103/Kconfig.soc b/soc/riscv/gd_gd32/gd32vf103/Kconfig.soc similarity index 100% rename from soc/riscv/riscv-privileged/gd32vf103/Kconfig.soc rename to soc/riscv/gd_gd32/gd32vf103/Kconfig.soc diff --git a/soc/riscv/riscv-privileged/gd32vf103/entry.S b/soc/riscv/gd_gd32/gd32vf103/entry.S similarity index 97% rename from soc/riscv/riscv-privileged/gd32vf103/entry.S rename to soc/riscv/gd_gd32/gd32vf103/entry.S index 5f8af0d691f5fce..41cc6cc686b348a 100644 --- a/soc/riscv/riscv-privileged/gd32vf103/entry.S +++ b/soc/riscv/gd_gd32/gd32vf103/entry.S @@ -4,9 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "nuclei_csr.h" + #include #include -#include GTEXT(__nuclei_start) SECTION_FUNC(vectors, __nuclei_start) diff --git a/soc/riscv/riscv-privileged/gd32vf103/gd32_regs.h b/soc/riscv/gd_gd32/gd32vf103/gd32_regs.h similarity index 100% rename from soc/riscv/riscv-privileged/gd32vf103/gd32_regs.h rename to soc/riscv/gd_gd32/gd32vf103/gd32_regs.h diff --git a/soc/riscv/riscv-privileged/common/nuclei/nuclei_csr.h b/soc/riscv/gd_gd32/gd32vf103/nuclei_csr.h similarity index 100% rename from soc/riscv/riscv-privileged/common/nuclei/nuclei_csr.h rename to soc/riscv/gd_gd32/gd32vf103/nuclei_csr.h diff --git a/soc/riscv/riscv-privileged/gd32vf103/pinctrl_soc.h b/soc/riscv/gd_gd32/gd32vf103/pinctrl_soc.h similarity index 100% rename from soc/riscv/riscv-privileged/gd32vf103/pinctrl_soc.h rename to soc/riscv/gd_gd32/gd32vf103/pinctrl_soc.h diff --git a/soc/riscv/riscv-privileged/gd32vf103/soc.c b/soc/riscv/gd_gd32/gd32vf103/soc.c similarity index 100% rename from soc/riscv/riscv-privileged/gd32vf103/soc.c rename to soc/riscv/gd_gd32/gd32vf103/soc.c diff --git a/soc/riscv/riscv-privileged/gd32vf103/soc.h b/soc/riscv/gd_gd32/gd32vf103/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/gd32vf103/soc.h rename to soc/riscv/gd_gd32/gd32vf103/soc.h diff --git a/soc/riscv/intel_niosv/CMakeLists.txt b/soc/riscv/intel_niosv/CMakeLists.txt new file mode 100644 index 000000000000000..69b2926358e5cf8 --- /dev/null +++ b/soc/riscv/intel_niosv/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(${SOC_SERIES}) diff --git a/soc/riscv/intel_niosv/Kconfig b/soc/riscv/intel_niosv/Kconfig new file mode 100644 index 000000000000000..b841d19c9227590 --- /dev/null +++ b/soc/riscv/intel_niosv/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_INTEL_NIOSV + bool + +if SOC_FAMILY_INTEL_NIOSV + +config SOC_FAMILY + string + default "intel_niosv" + +source "soc/riscv/intel_niosv/*/Kconfig.soc" + +endif # SOC_FAMILY_INTEL_NIOSV diff --git a/soc/riscv/intel_niosv/Kconfig.defconfig b/soc/riscv/intel_niosv/Kconfig.defconfig new file mode 100644 index 000000000000000..2afa0f7e0e60599 --- /dev/null +++ b/soc/riscv/intel_niosv/Kconfig.defconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/intel_niosv/*/Kconfig.defconfig.series" diff --git a/soc/riscv/intel_niosv/Kconfig.soc b/soc/riscv/intel_niosv/Kconfig.soc new file mode 100644 index 000000000000000..8567429c61f6c43 --- /dev/null +++ b/soc/riscv/intel_niosv/Kconfig.soc @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/intel_niosv/*/Kconfig.series" diff --git a/soc/riscv/riscv-privileged/niosv/CMakeLists.txt b/soc/riscv/intel_niosv/niosv/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/niosv/CMakeLists.txt rename to soc/riscv/intel_niosv/niosv/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/niosv/Kconfig.defconfig.series b/soc/riscv/intel_niosv/niosv/Kconfig.defconfig.series similarity index 94% rename from soc/riscv/riscv-privileged/niosv/Kconfig.defconfig.series rename to soc/riscv/intel_niosv/niosv/Kconfig.defconfig.series index 532a67959d2c3c9..8e8ea255202d41f 100644 --- a/soc/riscv/riscv-privileged/niosv/Kconfig.defconfig.series +++ b/soc/riscv/intel_niosv/niosv/Kconfig.defconfig.series @@ -21,4 +21,4 @@ config RISCV_GP config RISCV_SOC_INTERRUPT_INIT default y -endif # SOC_SERIES_NIOSV +endif # SOC_NIOSV diff --git a/soc/riscv/riscv-privileged/niosv/Kconfig.series b/soc/riscv/intel_niosv/niosv/Kconfig.series similarity index 77% rename from soc/riscv/riscv-privileged/niosv/Kconfig.series rename to soc/riscv/intel_niosv/niosv/Kconfig.series index 7de17cf2db09a66..9d7aa4926921cba 100644 --- a/soc/riscv/riscv-privileged/niosv/Kconfig.series +++ b/soc/riscv/intel_niosv/niosv/Kconfig.series @@ -4,6 +4,7 @@ config SOC_SERIES_NIOSV bool "INTEL FPGA NIOSV" select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED + select RISCV_PRIVILEGED + select SOC_FAMILY_INTEL_NIOSV help Enable support for the INTEL FPGA NIOSV. diff --git a/soc/riscv/riscv-privileged/niosv/Kconfig.soc b/soc/riscv/intel_niosv/niosv/Kconfig.soc similarity index 100% rename from soc/riscv/riscv-privileged/niosv/Kconfig.soc rename to soc/riscv/intel_niosv/niosv/Kconfig.soc diff --git a/soc/riscv/riscv-privileged/niosv/linker.ld b/soc/riscv/intel_niosv/niosv/linker.ld similarity index 100% rename from soc/riscv/riscv-privileged/niosv/linker.ld rename to soc/riscv/intel_niosv/niosv/linker.ld diff --git a/soc/riscv/riscv-privileged/niosv/soc.h b/soc/riscv/intel_niosv/niosv/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/niosv/soc.h rename to soc/riscv/intel_niosv/niosv/soc.h diff --git a/soc/riscv/riscv-ite/CMakeLists.txt b/soc/riscv/ite_ec/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-ite/CMakeLists.txt rename to soc/riscv/ite_ec/CMakeLists.txt diff --git a/soc/riscv/ite_ec/Kconfig b/soc/riscv/ite_ec/Kconfig new file mode 100644 index 000000000000000..54628029a4ece11 --- /dev/null +++ b/soc/riscv/ite_ec/Kconfig @@ -0,0 +1,17 @@ +# Copyright (c) 2020 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_ITE_EC + bool + help + ITE Embedded Controller SoC family + +if SOC_FAMILY_ITE_EC + +config SOC_FAMILY + string + default "ite_ec" + +source "soc/riscv/ite_ec/*/Kconfig.soc" + +endif # SOC_FAMILY_ITE_EC diff --git a/soc/riscv/riscv-ite/Kconfig.defconfig b/soc/riscv/ite_ec/Kconfig.defconfig similarity index 63% rename from soc/riscv/riscv-ite/Kconfig.defconfig rename to soc/riscv/ite_ec/Kconfig.defconfig index ae18beac098b4e1..8994f47abd9c873 100644 --- a/soc/riscv/riscv-ite/Kconfig.defconfig +++ b/soc/riscv/ite_ec/Kconfig.defconfig @@ -1,4 +1,4 @@ # Copyright (c) 2020 ITE Corporation. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -source "soc/riscv/riscv-ite/*/Kconfig.defconfig.series" +source "soc/riscv/ite_ec/*/Kconfig.defconfig.series" diff --git a/soc/riscv/riscv-ite/Kconfig.soc b/soc/riscv/ite_ec/Kconfig.soc similarity index 68% rename from soc/riscv/riscv-ite/Kconfig.soc rename to soc/riscv/ite_ec/Kconfig.soc index 925edb1543ce660..13f951c04666c32 100644 --- a/soc/riscv/riscv-ite/Kconfig.soc +++ b/soc/riscv/ite_ec/Kconfig.soc @@ -1,4 +1,4 @@ # Copyright (c) 2020 ITE Corporation. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -source "soc/riscv/riscv-ite/*/Kconfig.series" +source "soc/riscv/ite_ec/*/Kconfig.series" diff --git a/soc/riscv/riscv-ite/common/CMakeLists.txt b/soc/riscv/ite_ec/common/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-ite/common/CMakeLists.txt rename to soc/riscv/ite_ec/common/CMakeLists.txt diff --git a/soc/riscv/riscv-ite/common/check_regs.c b/soc/riscv/ite_ec/common/check_regs.c similarity index 100% rename from soc/riscv/riscv-ite/common/check_regs.c rename to soc/riscv/ite_ec/common/check_regs.c diff --git a/soc/riscv/riscv-ite/common/chip_chipregs.h b/soc/riscv/ite_ec/common/chip_chipregs.h similarity index 100% rename from soc/riscv/riscv-ite/common/chip_chipregs.h rename to soc/riscv/ite_ec/common/chip_chipregs.h diff --git a/soc/riscv/riscv-ite/common/pinctrl_soc.h b/soc/riscv/ite_ec/common/pinctrl_soc.h similarity index 100% rename from soc/riscv/riscv-ite/common/pinctrl_soc.h rename to soc/riscv/ite_ec/common/pinctrl_soc.h diff --git a/soc/riscv/riscv-ite/common/policy.c b/soc/riscv/ite_ec/common/policy.c similarity index 100% rename from soc/riscv/riscv-ite/common/policy.c rename to soc/riscv/ite_ec/common/policy.c diff --git a/soc/riscv/riscv-ite/common/power.c b/soc/riscv/ite_ec/common/power.c similarity index 100% rename from soc/riscv/riscv-ite/common/power.c rename to soc/riscv/ite_ec/common/power.c diff --git a/soc/riscv/riscv-ite/common/soc_common.h b/soc/riscv/ite_ec/common/soc_common.h similarity index 100% rename from soc/riscv/riscv-ite/common/soc_common.h rename to soc/riscv/ite_ec/common/soc_common.h diff --git a/soc/riscv/riscv-ite/common/soc_common_irq.c b/soc/riscv/ite_ec/common/soc_common_irq.c similarity index 100% rename from soc/riscv/riscv-ite/common/soc_common_irq.c rename to soc/riscv/ite_ec/common/soc_common_irq.c diff --git a/soc/riscv/riscv-ite/common/soc_dt.h b/soc/riscv/ite_ec/common/soc_dt.h similarity index 100% rename from soc/riscv/riscv-ite/common/soc_dt.h rename to soc/riscv/ite_ec/common/soc_dt.h diff --git a/soc/riscv/riscv-ite/common/soc_espi.h b/soc/riscv/ite_ec/common/soc_espi.h similarity index 100% rename from soc/riscv/riscv-ite/common/soc_espi.h rename to soc/riscv/ite_ec/common/soc_espi.h diff --git a/soc/riscv/riscv-ite/common/soc_irq.S b/soc/riscv/ite_ec/common/soc_irq.S similarity index 100% rename from soc/riscv/riscv-ite/common/soc_irq.S rename to soc/riscv/ite_ec/common/soc_irq.S diff --git a/soc/riscv/riscv-ite/common/vector.S b/soc/riscv/ite_ec/common/vector.S similarity index 100% rename from soc/riscv/riscv-ite/common/vector.S rename to soc/riscv/ite_ec/common/vector.S diff --git a/soc/riscv/riscv-ite/it8xxx2/CMakeLists.txt b/soc/riscv/ite_ec/it8xxx2/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/CMakeLists.txt rename to soc/riscv/ite_ec/it8xxx2/CMakeLists.txt diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it81202bx b/soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it81202bx similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it81202bx rename to soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it81202bx diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it81202cx b/soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it81202cx similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it81202cx rename to soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it81202cx diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it81302bx b/soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it81302bx similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it81302bx rename to soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it81302bx diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it81302cx b/soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it81302cx similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it81302cx rename to soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it81302cx diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it82002aw b/soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it82002aw similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it82002aw rename to soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it82002aw diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it82202ax b/soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it82202ax similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it82202ax rename to soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it82202ax diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it82302ax b/soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it82302ax similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it82302ax rename to soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it82302ax diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.series b/soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.series similarity index 87% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.series rename to soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.series index 4e6b7c18cca32ff..7c5bc0ee897055f 100644 --- a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.series +++ b/soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.series @@ -1,7 +1,7 @@ # Copyright (c) 2020 ITE Corporation. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_RISCV32_IT8XXX2 +if SOC_SERIES_ITE_IT8XXX2 config SOC_SERIES default "it8xxx2" @@ -57,6 +57,6 @@ config GEN_SW_ISR_TABLE config RISCV_SOC_INTERRUPT_INIT default y -source "soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.it8*" +source "soc/riscv/ite_ec/it8xxx2/Kconfig.defconfig.it8*" -endif # SOC_SERIES_RISCV32_IT8XXX2 +endif # SOC_SERIES_ITE_IT8XXX2 diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.series b/soc/riscv/ite_ec/it8xxx2/Kconfig.series similarity index 86% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.series rename to soc/riscv/ite_ec/it8xxx2/Kconfig.series index ebed0fcd120ef4d..265bf855f12c30b 100644 --- a/soc/riscv/riscv-ite/it8xxx2/Kconfig.series +++ b/soc/riscv/ite_ec/it8xxx2/Kconfig.series @@ -1,13 +1,13 @@ # Copyright (c) 2020 ITE Corporation. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -config SOC_SERIES_RISCV32_IT8XXX2 +config SOC_SERIES_ITE_IT8XXX2 bool "ITE IT8XXX2 implementation" #depends on RISCV # RV32IAFC is an uncommon configuration which is not supported by # default in most toolchains, causing link-time errors. select CPU_HAS_FPU if "$(ZEPHYR_TOOLCHAIN_VARIANT)" != "zephyr" || RISCV_ISA_EXT_M - select SOC_FAMILY_RISCV_ITE + select SOC_FAMILY_ITE_EC select HAS_PM help Enable support for ITE IT8XXX2 diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.soc b/soc/riscv/ite_ec/it8xxx2/Kconfig.soc similarity index 99% rename from soc/riscv/riscv-ite/it8xxx2/Kconfig.soc rename to soc/riscv/ite_ec/it8xxx2/Kconfig.soc index 38525449f89f1b6..800a2a9dafd7da6 100644 --- a/soc/riscv/riscv-ite/it8xxx2/Kconfig.soc +++ b/soc/riscv/ite_ec/it8xxx2/Kconfig.soc @@ -3,7 +3,7 @@ choice prompt "ITE IT8XXX2 system implementation" -depends on SOC_SERIES_RISCV32_IT8XXX2 +depends on SOC_SERIES_ITE_IT8XXX2 config SOC_IT8XXX2 bool "ITE IT8XXX2 system implementation" diff --git a/soc/riscv/riscv-ite/it8xxx2/__arithmetic.S b/soc/riscv/ite_ec/it8xxx2/__arithmetic.S similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/__arithmetic.S rename to soc/riscv/ite_ec/it8xxx2/__arithmetic.S diff --git a/soc/riscv/riscv-ite/it8xxx2/ilm.c b/soc/riscv/ite_ec/it8xxx2/ilm.c similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/ilm.c rename to soc/riscv/ite_ec/it8xxx2/ilm.c diff --git a/soc/riscv/riscv-ite/it8xxx2/ilm.h b/soc/riscv/ite_ec/it8xxx2/ilm.h similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/ilm.h rename to soc/riscv/ite_ec/it8xxx2/ilm.h diff --git a/soc/riscv/riscv-ite/it8xxx2/linker.ld b/soc/riscv/ite_ec/it8xxx2/linker.ld similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/linker.ld rename to soc/riscv/ite_ec/it8xxx2/linker.ld diff --git a/soc/riscv/riscv-ite/it8xxx2/soc.c b/soc/riscv/ite_ec/it8xxx2/soc.c similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/soc.c rename to soc/riscv/ite_ec/it8xxx2/soc.c diff --git a/soc/riscv/riscv-ite/it8xxx2/soc.h b/soc/riscv/ite_ec/it8xxx2/soc.h similarity index 100% rename from soc/riscv/riscv-ite/it8xxx2/soc.h rename to soc/riscv/ite_ec/it8xxx2/soc.h diff --git a/soc/riscv/litex-vexriscv/CMakeLists.txt b/soc/riscv/litex_vexriscv/CMakeLists.txt similarity index 73% rename from soc/riscv/litex-vexriscv/CMakeLists.txt rename to soc/riscv/litex_vexriscv/CMakeLists.txt index 9d100ea0e2a35ef..98386f6b57a60de 100644 --- a/soc/riscv/litex-vexriscv/CMakeLists.txt +++ b/soc/riscv/litex_vexriscv/CMakeLists.txt @@ -5,8 +5,8 @@ # zephyr_sources( - ../riscv-privileged/common/soc_irq.S - ../riscv-privileged/common/vector.S + ../common/riscv-privileged/soc_irq.S + ../common/riscv-privileged/vector.S ) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/litex-vexriscv/Kconfig.defconfig b/soc/riscv/litex_vexriscv/Kconfig.defconfig similarity index 92% rename from soc/riscv/litex-vexriscv/Kconfig.defconfig rename to soc/riscv/litex_vexriscv/Kconfig.defconfig index 9447948b56764b1..3efdf200ee724e2 100644 --- a/soc/riscv/litex-vexriscv/Kconfig.defconfig +++ b/soc/riscv/litex_vexriscv/Kconfig.defconfig @@ -4,7 +4,7 @@ if SOC_RISCV32_LITEX_VEXRISCV config SOC - default "litex-vexriscv" + default "litex_vexriscv" config SYS_CLOCK_HW_CYCLES_PER_SEC default 100000000 diff --git a/soc/riscv/litex-vexriscv/Kconfig.soc b/soc/riscv/litex_vexriscv/Kconfig.soc similarity index 100% rename from soc/riscv/litex-vexriscv/Kconfig.soc rename to soc/riscv/litex_vexriscv/Kconfig.soc diff --git a/soc/riscv/litex-vexriscv/soc.h b/soc/riscv/litex_vexriscv/soc.h similarity index 98% rename from soc/riscv/litex-vexriscv/soc.h rename to soc/riscv/litex_vexriscv/soc.h index b738deec771372b..b3521b51e8effda 100644 --- a/soc/riscv/litex-vexriscv/soc.h +++ b/soc/riscv/litex_vexriscv/soc.h @@ -7,7 +7,7 @@ #ifndef __RISCV32_LITEX_VEXRISCV_SOC_H_ #define __RISCV32_LITEX_VEXRISCV_SOC_H_ -#include "../riscv-privileged/common/soc_common.h" +#include "../common/riscv-privileged/soc_common.h" #include #include diff --git a/soc/riscv/microchip_miv/CMakeLists.txt b/soc/riscv/microchip_miv/CMakeLists.txt new file mode 100644 index 000000000000000..69b2926358e5cf8 --- /dev/null +++ b/soc/riscv/microchip_miv/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(${SOC_SERIES}) diff --git a/soc/riscv/microchip_miv/Kconfig b/soc/riscv/microchip_miv/Kconfig new file mode 100644 index 000000000000000..46616636aa1277a --- /dev/null +++ b/soc/riscv/microchip_miv/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_MICROCHIP_MIV + bool + +if SOC_FAMILY_MICROCHIP_MIV + +config SOC_FAMILY + string + default "microchip_miv" + +source "soc/riscv/microchip_miv/*/Kconfig.soc" + +endif # SOC_FAMILY_MICROCHIP_MIV diff --git a/soc/riscv/microchip_miv/Kconfig.defconfig b/soc/riscv/microchip_miv/Kconfig.defconfig new file mode 100644 index 000000000000000..2fe508bddbac0ef --- /dev/null +++ b/soc/riscv/microchip_miv/Kconfig.defconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/microchip_miv/*/Kconfig.defconfig.series" diff --git a/soc/riscv/microchip_miv/Kconfig.soc b/soc/riscv/microchip_miv/Kconfig.soc new file mode 100644 index 000000000000000..8677f1ba44875a0 --- /dev/null +++ b/soc/riscv/microchip_miv/Kconfig.soc @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/microchip_miv/*/Kconfig.series" diff --git a/soc/riscv/riscv-privileged/miv/CMakeLists.txt b/soc/riscv/microchip_miv/miv/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/miv/CMakeLists.txt rename to soc/riscv/microchip_miv/miv/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/miv/Kconfig.defconfig.series b/soc/riscv/microchip_miv/miv/Kconfig.defconfig.series similarity index 88% rename from soc/riscv/riscv-privileged/miv/Kconfig.defconfig.series rename to soc/riscv/microchip_miv/miv/Kconfig.defconfig.series index 81b224ed3971db6..ef161321a5b7bf2 100644 --- a/soc/riscv/riscv-privileged/miv/Kconfig.defconfig.series +++ b/soc/riscv/microchip_miv/miv/Kconfig.defconfig.series @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_RISCV32_MIV +if SOC_SERIES_MIV config SOC_SERIES default "miv" @@ -32,4 +32,4 @@ config MAX_IRQ_PER_AGGREGATOR config NUM_IRQS default 42 -endif # SOC_SERIES_RISCV32_MIV +endif # SOC_SERIES_MIV diff --git a/soc/riscv/riscv-privileged/miv/Kconfig.series b/soc/riscv/microchip_miv/miv/Kconfig.series similarity index 72% rename from soc/riscv/riscv-privileged/miv/Kconfig.series rename to soc/riscv/microchip_miv/miv/Kconfig.series index 00a6f129f9faaf3..2989876c0e08d2c 100644 --- a/soc/riscv/riscv-privileged/miv/Kconfig.series +++ b/soc/riscv/microchip_miv/miv/Kconfig.series @@ -3,9 +3,10 @@ # Copyright (c) 2018 Antmicro # SPDX-License-Identifier: Apache-2.0 -config SOC_SERIES_RISCV32_MIV +config SOC_SERIES_MIV bool "Microchip Mi-V implementation" + select SOC_FAMILY_MICROCHIP_MIV select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED + select RISCV_PRIVILEGED help Enable support for Microchip Mi-V diff --git a/soc/riscv/riscv-privileged/miv/Kconfig.soc b/soc/riscv/microchip_miv/miv/Kconfig.soc similarity index 88% rename from soc/riscv/riscv-privileged/miv/Kconfig.soc rename to soc/riscv/microchip_miv/miv/Kconfig.soc index 189abb6879ce962..0a48c2e0524e41d 100644 --- a/soc/riscv/riscv-privileged/miv/Kconfig.soc +++ b/soc/riscv/microchip_miv/miv/Kconfig.soc @@ -5,9 +5,9 @@ choice prompt "Microchip Mi-V system implementation" - depends on SOC_SERIES_RISCV32_MIV + depends on SOC_SERIES_MIV -config SOC_RISCV32_MIV +config SOC_MIV bool "Microchip Mi-V system implementation" select ATOMIC_OPERATIONS_BUILTIN select INCLUDE_RESET_VECTOR diff --git a/soc/riscv/riscv-privileged/miv/soc.h b/soc/riscv/microchip_miv/miv/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/miv/soc.h rename to soc/riscv/microchip_miv/miv/soc.h diff --git a/soc/riscv/riscv-privileged/mpfs/CMakeLists.txt b/soc/riscv/microchip_miv/polarfire/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/mpfs/CMakeLists.txt rename to soc/riscv/microchip_miv/polarfire/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/mpfs/Kconfig.defconfig.series b/soc/riscv/microchip_miv/polarfire/Kconfig.defconfig.series similarity index 88% rename from soc/riscv/riscv-privileged/mpfs/Kconfig.defconfig.series rename to soc/riscv/microchip_miv/polarfire/Kconfig.defconfig.series index 12f9dcaa992e82c..e5c3a2ebce982bd 100644 --- a/soc/riscv/riscv-privileged/mpfs/Kconfig.defconfig.series +++ b/soc/riscv/microchip_miv/polarfire/Kconfig.defconfig.series @@ -1,10 +1,10 @@ # Copyright (c) 2020-2021 Microchip Technology Inc # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_RISCV64_MIV +if SOC_SERIES_POLARFIRE config SOC_SERIES - default "mpfs" + default "polarfire" # MPFS should be configured so that the mtimer clock is 1MHz independent of the CPU clock... @@ -35,4 +35,4 @@ config MAX_IRQ_PER_AGGREGATOR config NUM_IRQS default 186 -endif # SOC_SERIES_RISCV64_MIV +endif # SOC_SERIES_POLARFIRE diff --git a/soc/riscv/riscv-privileged/mpfs/Kconfig.series b/soc/riscv/microchip_miv/polarfire/Kconfig.series similarity index 71% rename from soc/riscv/riscv-privileged/mpfs/Kconfig.series rename to soc/riscv/microchip_miv/polarfire/Kconfig.series index ca37731f1925132..9001efc2858816f 100644 --- a/soc/riscv/riscv-privileged/mpfs/Kconfig.series +++ b/soc/riscv/microchip_miv/polarfire/Kconfig.series @@ -3,9 +3,10 @@ # Copyright (c) 2018 Antmicro # SPDX-License-Identifier: Apache-2.0 -config SOC_SERIES_RISCV64_MIV +config SOC_SERIES_POLARFIRE bool "Microchip RV64 implementation" + select SOC_FAMILY_MICROCHIP_MIV select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED + select RISCV_PRIVILEGED help Enable support for Microchip RISCV 64bit diff --git a/soc/riscv/riscv-privileged/mpfs/Kconfig.soc b/soc/riscv/microchip_miv/polarfire/Kconfig.soc similarity index 89% rename from soc/riscv/riscv-privileged/mpfs/Kconfig.soc rename to soc/riscv/microchip_miv/polarfire/Kconfig.soc index 7f20dc703c2275b..101e8b4d02940b9 100644 --- a/soc/riscv/riscv-privileged/mpfs/Kconfig.soc +++ b/soc/riscv/microchip_miv/polarfire/Kconfig.soc @@ -5,9 +5,9 @@ choice prompt "Microchip Polarfire SOC implementation" - depends on SOC_SERIES_RISCV64_MIV + depends on SOC_SERIES_POLARFIRE -config SOC_MPFS +config SOC_POLARFIRE bool "Microchip MPFS system implementation" select ATOMIC_OPERATIONS_BUILTIN select RISCV_GP @@ -25,6 +25,6 @@ config SOC_MPFS endchoice config MPFS_HAL - depends on SOC_MPFS + depends on SOC_POLARFIRE bool "Microchip Polarfire SOC hardware abstracton layer" select HAS_MPFS_HAL diff --git a/soc/riscv/riscv-privileged/mpfs/soc.h b/soc/riscv/microchip_miv/polarfire/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/mpfs/soc.h rename to soc/riscv/microchip_miv/polarfire/soc.h diff --git a/soc/riscv/riscv-privileged/neorv32/CMakeLists.txt b/soc/riscv/neorv32/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/neorv32/CMakeLists.txt rename to soc/riscv/neorv32/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/neorv32/Kconfig.defconfig.series b/soc/riscv/neorv32/Kconfig.defconfig similarity index 88% rename from soc/riscv/riscv-privileged/neorv32/Kconfig.defconfig.series rename to soc/riscv/neorv32/Kconfig.defconfig index 11bd7ef7d337f8c..86aed551f5de5ae 100644 --- a/soc/riscv/riscv-privileged/neorv32/Kconfig.defconfig.series +++ b/soc/riscv/neorv32/Kconfig.defconfig @@ -1,9 +1,9 @@ # Copyright (c) 2021 Henrik Brix Andersen # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_NEORV32 +if SOC_NEORV32 -config SOC_SERIES +config SOC default "neorv32" config SYS_CLOCK_HW_CYCLES_PER_SEC @@ -29,4 +29,4 @@ config ENTROPY_INIT_PRIORITY default 55 depends on ENTROPY_GENERATOR -endif # SOC_SERIES_NEORV32 +endif # SOC_NEORV32 diff --git a/soc/riscv/riscv-privileged/neorv32/Kconfig.series b/soc/riscv/neorv32/Kconfig.soc similarity index 55% rename from soc/riscv/riscv-privileged/neorv32/Kconfig.series rename to soc/riscv/neorv32/Kconfig.soc index 98c7f34024d2601..3155d1b7c31c2cf 100644 --- a/soc/riscv/riscv-privileged/neorv32/Kconfig.series +++ b/soc/riscv/neorv32/Kconfig.soc @@ -1,7 +1,7 @@ # Copyright (c) 2021 Henrik Brix Andersen # SPDX-License-Identifier: Apache-2.0 -config SOC_SERIES_NEORV32 +config SOC_NEORV32 bool "NEORV32 Processor" select RISCV select RISCV_ISA_RV32I @@ -9,7 +9,7 @@ config SOC_SERIES_NEORV32 select RISCV_ISA_EXT_A select RISCV_ISA_EXT_ZICSR select RISCV_ISA_EXT_ZIFENCEI - select SOC_FAMILY_RISCV_PRIVILEGED + select RISCV_PRIVILEGED help Enable support for the NEORV32 Processor (SoC). @@ -24,3 +24,27 @@ config SOC_SERIES_NEORV32 - E (Embedded, only 16 integer registers) - Zbb (Basic Bit Manipulation) - Zfinx (Floating Point in Integer Registers) + +if SOC_NEORV32 + +config SOC_NEORV32_V1_8_6 + bool "v1.8.6" + # NEORV32 RISC-V ISA A extension implements only LR/SC, not AMO + select ATOMIC_OPERATIONS_C + +config SOC_NEORV32_VERSION + hex + default 0x01080600 if SOC_NEORV32_V1_8_6 + help + The targeted NEORV32 version as BCD-coded number. The format is + identical to that of the NEORV32 Machine implementation ID (mimpid) + register. + +config SOC_NEORV32_ISA_C + bool "RISC-V ISA Extension \"C\"" + select RISCV_ISA_EXT_C + help + Enable this if the NEORV32 CPU implementation supports the RISC-V ISA + "C" extension (Compressed Instructions). + +endif # SOC_NEORV32 diff --git a/soc/riscv/riscv-privileged/neorv32/linker.ld b/soc/riscv/neorv32/linker.ld similarity index 100% rename from soc/riscv/riscv-privileged/neorv32/linker.ld rename to soc/riscv/neorv32/linker.ld diff --git a/soc/riscv/riscv-privileged/neorv32/reset.S b/soc/riscv/neorv32/reset.S similarity index 100% rename from soc/riscv/riscv-privileged/neorv32/reset.S rename to soc/riscv/neorv32/reset.S diff --git a/soc/riscv/riscv-privileged/neorv32/soc.c b/soc/riscv/neorv32/soc.c similarity index 100% rename from soc/riscv/riscv-privileged/neorv32/soc.c rename to soc/riscv/neorv32/soc.c diff --git a/soc/riscv/riscv-privileged/neorv32/soc.h b/soc/riscv/neorv32/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/neorv32/soc.h rename to soc/riscv/neorv32/soc.h diff --git a/soc/riscv/riscv-privileged/neorv32/soc_irq.S b/soc/riscv/neorv32/soc_irq.S similarity index 100% rename from soc/riscv/riscv-privileged/neorv32/soc_irq.S rename to soc/riscv/neorv32/soc_irq.S diff --git a/soc/riscv/riscv-privileged/opentitan/CMakeLists.txt b/soc/riscv/opentitan/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/opentitan/CMakeLists.txt rename to soc/riscv/opentitan/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/opentitan/Kconfig.defconfig.series b/soc/riscv/opentitan/Kconfig.defconfig similarity index 83% rename from soc/riscv/riscv-privileged/opentitan/Kconfig.defconfig.series rename to soc/riscv/opentitan/Kconfig.defconfig index c9e7f8396a0f431..cc27b7ffd6b6cd9 100644 --- a/soc/riscv/riscv-privileged/opentitan/Kconfig.defconfig.series +++ b/soc/riscv/opentitan/Kconfig.defconfig @@ -1,9 +1,9 @@ # Copyright (c) 2023 Rivos Inc. # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_RISCV_OPENTITAN +if SOC_OPENTITAN -config SOC_SERIES +config SOC default "opentitan" config SYS_CLOCK_HW_CYCLES_PER_SEC @@ -30,4 +30,4 @@ config 2ND_LVL_INTR_00_OFFSET config NUM_IRQS default 217 -endif # SOC_SERIES_RISCV_OPENTITAN +endif # SOC_OPENTITAN diff --git a/soc/riscv/riscv-privileged/opentitan/Kconfig.soc b/soc/riscv/opentitan/Kconfig.soc similarity index 67% rename from soc/riscv/riscv-privileged/opentitan/Kconfig.soc rename to soc/riscv/opentitan/Kconfig.soc index 098b1844e52e08c..8270fde110d5fd2 100644 --- a/soc/riscv/riscv-privileged/opentitan/Kconfig.soc +++ b/soc/riscv/opentitan/Kconfig.soc @@ -1,11 +1,7 @@ # Copyright (c) 2023 Rivos Inc. # SPDX-License-Identifier: Apache-2.0 -choice - prompt "OpenTitan implementation" - depends on SOC_SERIES_RISCV_OPENTITAN - -config SOC_RISCV_OPENTITAN +config SOC_OPENTITAN bool "OpenTitan implementation" select ATOMIC_OPERATIONS_C select INCLUDE_RESET_VECTOR @@ -18,5 +14,8 @@ config SOC_RISCV_OPENTITAN select RISCV_ISA_EXT_ZBB select RISCV_ISA_EXT_ZBC select RISCV_ISA_EXT_ZBS - -endchoice + select RISCV + select RISCV_PRIVILEGED + # OpenTitan Ibex core mtvec mode is read-only / forced to vectored mode. + select RISCV_VECTORED_MODE + select GEN_IRQ_VECTOR_TABLE diff --git a/soc/riscv/riscv-privileged/opentitan/rom_header.S b/soc/riscv/opentitan/rom_header.S similarity index 100% rename from soc/riscv/riscv-privileged/opentitan/rom_header.S rename to soc/riscv/opentitan/rom_header.S diff --git a/soc/riscv/riscv-privileged/opentitan/rom_header.ld b/soc/riscv/opentitan/rom_header.ld similarity index 100% rename from soc/riscv/riscv-privileged/opentitan/rom_header.ld rename to soc/riscv/opentitan/rom_header.ld diff --git a/soc/riscv/riscv-privileged/opentitan/soc.c b/soc/riscv/opentitan/soc.c similarity index 100% rename from soc/riscv/riscv-privileged/opentitan/soc.c rename to soc/riscv/opentitan/soc.c diff --git a/soc/riscv/riscv-privileged/opentitan/soc.h b/soc/riscv/opentitan/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/opentitan/soc.h rename to soc/riscv/opentitan/soc.h diff --git a/soc/riscv/renode_virt/CMakeLists.txt b/soc/riscv/renode_virt/CMakeLists.txt new file mode 100644 index 000000000000000..56d36b84ec8bbcc --- /dev/null +++ b/soc/riscv/renode_virt/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources() + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/renode_virt/Kconfig.defconfig b/soc/riscv/renode_virt/Kconfig.defconfig new file mode 100644 index 000000000000000..89e226edbb1d256 --- /dev/null +++ b/soc/riscv/renode_virt/Kconfig.defconfig @@ -0,0 +1,48 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +if SOC_RISCV32_VIRTUAL_RENODE + +config SOC + default "renode_virt" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 4000000 + +config RISCV_SOC_INTERRUPT_INIT + default y + +config RISCV_HAS_CPU_IDLE + default y + +config RISCV_HAS_PLIC + default y + +config RISCV_GP + default y + +config 1ST_LEVEL_INTERRUPT_BITS + default 4 + +config NUM_2ND_LEVEL_AGGREGATORS + default 2 + +config 2ND_LEVEL_INTERRUPT_BITS + default 11 + +config 2ND_LVL_ISR_TBL_OFFSET + default 12 + +config 2ND_LVL_INTR_00_OFFSET + default 11 + +config 2ND_LVL_INTR_01_OFFSET + default 4 + +config MAX_IRQ_PER_AGGREGATOR + default 1023 + +config NUM_IRQS + default 2058 + +endif # SOC_RISCV32_VIRTUAL_RENODE diff --git a/soc/riscv/renode_virt/Kconfig.soc b/soc/riscv/renode_virt/Kconfig.soc new file mode 100644 index 000000000000000..5aae660880a6832 --- /dev/null +++ b/soc/riscv/renode_virt/Kconfig.soc @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Meta +# SPDX-License-Identifier: Apache-2.0 + +config SOC_RISCV32_VIRTUAL_RENODE + bool "Renode RISCV32 Virtual system implementation" + select RISCV + select RISCV_PRIVILEGED + select ATOMIC_OPERATIONS_BUILTIN + select INCLUDE_RESET_VECTOR + select RISCV_ISA_RV32I + select RISCV_ISA_EXT_M + select RISCV_ISA_EXT_A + select RISCV_ISA_EXT_C + select RISCV_ISA_EXT_ZICSR + select RISCV_ISA_EXT_ZIFENCEI diff --git a/soc/riscv/renode_virt/soc.h b/soc/riscv/renode_virt/soc.h new file mode 100644 index 000000000000000..c82e16f1613cb2c --- /dev/null +++ b/soc/riscv/renode_virt/soc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __RISCV32_RENODE_SOC_H_ +#define __RISCV32_RENODE_SOC_H_ + +#include + +#endif /* __RISCV32_RENODE_SOC_H_ */ diff --git a/soc/riscv/riscv-ite/Kconfig b/soc/riscv/riscv-ite/Kconfig deleted file mode 100644 index f25c53d1ffb670d..000000000000000 --- a/soc/riscv/riscv-ite/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2020 ITE Corporation. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 - -config SOC_FAMILY_RISCV_ITE - bool - help - omit prompt to signify a "hidden" option - -config SOC_FAMILY - string - default "riscv-ite" - depends on SOC_FAMILY_RISCV_ITE - -source "soc/riscv/riscv-ite/*/Kconfig.soc" diff --git a/soc/riscv/riscv-privileged/Kconfig.defconfig b/soc/riscv/riscv-privileged/Kconfig.defconfig deleted file mode 100644 index 6793d72a385bd20..000000000000000 --- a/soc/riscv/riscv-privileged/Kconfig.defconfig +++ /dev/null @@ -1,6 +0,0 @@ -# riscv SOC family supporting the riscv privileged architecture spec - -# Copyright (c) 2017 Jean-Paul Etienne -# SPDX-License-Identifier: Apache-2.0 - -source "soc/riscv/riscv-privileged/*/Kconfig.defconfig.series" diff --git a/soc/riscv/riscv-privileged/Kconfig.soc b/soc/riscv/riscv-privileged/Kconfig.soc deleted file mode 100644 index 14d141223e0a434..000000000000000 --- a/soc/riscv/riscv-privileged/Kconfig.soc +++ /dev/null @@ -1,6 +0,0 @@ -# riscv SOC series supporting the riscv privileged architecture spec - -# Copyright (c) 2017 Jean-Paul Etienne -# SPDX-License-Identifier: Apache-2.0 - -source "soc/riscv/riscv-privileged/*/Kconfig.series" diff --git a/soc/riscv/riscv-privileged/andes_v5/Kconfig.series b/soc/riscv/riscv-privileged/andes_v5/Kconfig.series deleted file mode 100644 index 9a99711b04c633a..000000000000000 --- a/soc/riscv/riscv-privileged/andes_v5/Kconfig.series +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2021 Andes Technology Corporation -# SPDX-License-Identifier: Apache-2.0 - -config SOC_SERIES_RISCV_ANDES_V5 - bool "Andes V5 SoC Series Implementation" - select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED - help - Enable support for Andes V5 SoC Series diff --git a/soc/riscv/riscv-privileged/efinix-sapphire/Kconfig.series b/soc/riscv/riscv-privileged/efinix-sapphire/Kconfig.series deleted file mode 100644 index 8505cf1318a6d4b..000000000000000 --- a/soc/riscv/riscv-privileged/efinix-sapphire/Kconfig.series +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2023 Efinix Inc. -# SPDX-License-Identifier: Apache-2.0 - -config SOC_SERIES_EFINIX_SAPPHIRE - bool "Efinix Sapphire SOC implementation" - select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED - help - Enable support for Efinix Sapphire SOC implementation diff --git a/soc/riscv/riscv-privileged/neorv32/Kconfig.soc b/soc/riscv/riscv-privileged/neorv32/Kconfig.soc deleted file mode 100644 index 93c9da8cc3d46cb..000000000000000 --- a/soc/riscv/riscv-privileged/neorv32/Kconfig.soc +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2021 Henrik Brix Andersen -# SPDX-License-Identifier: Apache-2.0 - -choice - prompt "NEORV32 Version" - depends on SOC_SERIES_NEORV32 - -config SOC_NEORV32_V1_8_6 - bool "v1.8.6" - # NEORV32 RISC-V ISA A extension implements only LR/SC, not AMO - select ATOMIC_OPERATIONS_C - -endchoice - -if SOC_SERIES_NEORV32 - -config SOC_NEORV32_VERSION - hex - default 0x01080600 if SOC_NEORV32_V1_8_6 - help - The targeted NEORV32 version as BCD-coded number. The format is - identical to that of the NEORV32 Machine implementation ID (mimpid) - register. - -config SOC_NEORV32_ISA_C - bool "RISC-V ISA Extension \"C\"" - select RISCV_ISA_EXT_C - help - Enable this if the NEORV32 CPU implementation supports the RISC-V ISA - "C" extension (Compressed Instructions). - -endif # SOC_SERIES_NEORV32 diff --git a/soc/riscv/riscv-privileged/opentitan/Kconfig.series b/soc/riscv/riscv-privileged/opentitan/Kconfig.series deleted file mode 100644 index f8bbc2840fed7a5..000000000000000 --- a/soc/riscv/riscv-privileged/opentitan/Kconfig.series +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2023 Rivos Inc. -# SPDX-License-Identifier: Apache-2.0 - -config SOC_SERIES_RISCV_OPENTITAN - bool "OpenTitan implementation" - select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED - # OpenTitan Ibex core mtvec mode is read-only / forced to vectored mode. - select RISCV_VECTORED_MODE - select GEN_IRQ_VECTOR_TABLE - help - Enable support for OpenTitan diff --git a/soc/riscv/riscv-privileged/sifive-freedom/CMakeLists.txt b/soc/riscv/riscv-privileged/sifive-freedom/CMakeLists.txt deleted file mode 100644 index ff4cc56d7398fd3..000000000000000 --- a/soc/riscv/riscv-privileged/sifive-freedom/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_sources() -zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FREEDOM fe310_clock.c) -zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FU540 fu540_clock.c) -zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FU740 fu740_clock.c) - -set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/riscv-privileged/sifive-freedom/Kconfig.series b/soc/riscv/riscv-privileged/sifive-freedom/Kconfig.series deleted file mode 100644 index 523f6a4ffe97d9f..000000000000000 --- a/soc/riscv/riscv-privileged/sifive-freedom/Kconfig.series +++ /dev/null @@ -1,11 +0,0 @@ -# RISCV_SIFIVE_FREEDOM SOC implementation - -# Copyright (c) 2017 Jean-Paul Etienne -# SPDX-License-Identifier: Apache-2.0 - -config SOC_SERIES_RISCV_SIFIVE_FREEDOM - bool "SiFive Freedom SOC implementation" - select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED - help - Enable support for SiFive Freedom SOC diff --git a/soc/riscv/riscv-privileged/sifive-freedom/Kconfig.soc b/soc/riscv/riscv-privileged/sifive-freedom/Kconfig.soc deleted file mode 100644 index 7840f8a09ba79e5..000000000000000 --- a/soc/riscv/riscv-privileged/sifive-freedom/Kconfig.soc +++ /dev/null @@ -1,44 +0,0 @@ -# RISCV_SIFIVE_FREEDOM SOC configuration options - -# Copyright (c) 2017 Jean-Paul Etienne -# SPDX-License-Identifier: Apache-2.0 - -choice - prompt "SiFive Freedom SOC implementation" - depends on SOC_SERIES_RISCV_SIFIVE_FREEDOM - -config SOC_RISCV_SIFIVE_FREEDOM - bool "SiFive Freedom SOC implementation" - select ATOMIC_OPERATIONS_C - select INCLUDE_RESET_VECTOR - select RISCV_ISA_RV32I - select RISCV_ISA_EXT_M - select RISCV_ISA_EXT_A - select RISCV_ISA_EXT_ZICSR - select RISCV_ISA_EXT_ZIFENCEI - -config SOC_RISCV_SIFIVE_FU540 - bool "SiFive Freedom U540 SOC implementation" - select ATOMIC_OPERATIONS_C - select INCLUDE_RESET_VECTOR - select 64BIT - select RISCV_ISA_RV64I - select RISCV_ISA_EXT_M - select RISCV_ISA_EXT_A - select RISCV_ISA_EXT_C - select RISCV_ISA_EXT_ZICSR - select RISCV_ISA_EXT_ZIFENCEI - -config SOC_RISCV_SIFIVE_FU740 - bool "SiFive Freedom U740 SOC implementation" - select ATOMIC_OPERATIONS_C - select INCLUDE_RESET_VECTOR - select 64BIT - select RISCV_ISA_RV64I - select RISCV_ISA_EXT_M - select RISCV_ISA_EXT_A - select RISCV_ISA_EXT_C - select RISCV_ISA_EXT_ZICSR - select RISCV_ISA_EXT_ZIFENCEI - -endchoice diff --git a/soc/riscv/riscv-privileged/telink_b91/Kconfig.soc b/soc/riscv/riscv-privileged/telink_b91/Kconfig.soc deleted file mode 100644 index 3f4f96c332e593f..000000000000000 --- a/soc/riscv/riscv-privileged/telink_b91/Kconfig.soc +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2021 Telink Semiconductor -# SPDX-License-Identifier: Apache-2.0 - -choice -prompt "CPU Architecture of SoC" -depends on SOC_SERIES_RISCV_TELINK_B91 - -config B91_CPU_RISCV32 - bool "RISCV32 CPU Architecture" - select RISCV_ISA_RV32I - select RISCV_ISA_EXT_M - select RISCV_ISA_EXT_A - select RISCV_ISA_EXT_C - select RISCV_ISA_EXT_ZICSR - select RISCV_ISA_EXT_ZIFENCEI - -endchoice - -config TELINK_B91_HWDSP - bool "Support Hardware DSP" - select RISCV_SOC_CONTEXT_SAVE - depends on SOC_SERIES_RISCV_TELINK_B91 - -config TELINK_B91_PFT_ARCH - bool "Support performance throttling" - default y - select RISCV_SOC_CONTEXT_SAVE - depends on SOC_SERIES_RISCV_TELINK_B91 - -choice -prompt "Telink B91 SoC implementation" -depends on SOC_SERIES_RISCV_TELINK_B91 - -config SOC_RISCV_TELINK_B91 - bool "Telink B91 SoC implementation" - select ATOMIC_OPERATIONS_BUILTIN - select CPU_HAS_FPU - select INCLUDE_RESET_VECTOR - -endchoice diff --git a/soc/riscv/riscv-privileged/virt/Kconfig.series b/soc/riscv/riscv-privileged/virt/Kconfig.series deleted file mode 100644 index e9846764f6baebd..000000000000000 --- a/soc/riscv/riscv-privileged/virt/Kconfig.series +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2020 Cobham Gaisler AB -# SPDX-License-Identifier: Apache-2.0 - -config SOC_SERIES_RISCV_VIRT - bool "QEMU RISC-V VirtIO Board" - select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED diff --git a/soc/riscv/riscv-privileged/CMakeLists.txt b/soc/riscv/sifive_freedom/CMakeLists.txt similarity index 69% rename from soc/riscv/riscv-privileged/CMakeLists.txt rename to soc/riscv/sifive_freedom/CMakeLists.txt index c5f97039eb75b46..6a5b10545ff103e 100644 --- a/soc/riscv/riscv-privileged/CMakeLists.txt +++ b/soc/riscv/sifive_freedom/CMakeLists.txt @@ -1,3 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor # SPDX-License-Identifier: Apache-2.0 add_subdirectory(common) diff --git a/soc/riscv/sifive_freedom/Kconfig b/soc/riscv/sifive_freedom/Kconfig new file mode 100644 index 000000000000000..0fed11158afca52 --- /dev/null +++ b/soc/riscv/sifive_freedom/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_SIFIVE_FREEDOM + bool + +if SOC_FAMILY_SIFIVE_FREEDOM + +config SOC_FAMILY + string + default "sifive_freedom" + +source "soc/riscv/sifive_freedom/*/Kconfig.soc" + +endif # SOC_FAMILY_SIFIVE_FREEDOM diff --git a/soc/riscv/sifive_freedom/Kconfig.defconfig b/soc/riscv/sifive_freedom/Kconfig.defconfig new file mode 100644 index 000000000000000..5adf8fc437e54c0 --- /dev/null +++ b/soc/riscv/sifive_freedom/Kconfig.defconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/sifive_freedom/*/Kconfig.defconfig.series" diff --git a/soc/riscv/sifive_freedom/Kconfig.soc b/soc/riscv/sifive_freedom/Kconfig.soc new file mode 100644 index 000000000000000..54274defd919aad --- /dev/null +++ b/soc/riscv/sifive_freedom/Kconfig.soc @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/sifive_freedom/*/Kconfig.series" diff --git a/soc/riscv/sifive_freedom/common/CMakeLists.txt b/soc/riscv/sifive_freedom/common/CMakeLists.txt new file mode 100644 index 000000000000000..f75aec6b3117686 --- /dev/null +++ b/soc/riscv/sifive_freedom/common/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(.) diff --git a/soc/riscv/riscv-privileged/sifive-freedom/pinctrl_soc.h b/soc/riscv/sifive_freedom/common/pinctrl_soc.h similarity index 100% rename from soc/riscv/riscv-privileged/sifive-freedom/pinctrl_soc.h rename to soc/riscv/sifive_freedom/common/pinctrl_soc.h diff --git a/soc/riscv/sifive_freedom/e300/CMakeLists.txt b/soc/riscv/sifive_freedom/e300/CMakeLists.txt new file mode 100644 index 000000000000000..baf01a6b0473772 --- /dev/null +++ b/soc/riscv/sifive_freedom/e300/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources(clock.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/sifive_freedom/e300/Kconfig.defconfig.e340 b/soc/riscv/sifive_freedom/e300/Kconfig.defconfig.e340 new file mode 100644 index 000000000000000..cb0131f142706ac --- /dev/null +++ b/soc/riscv/sifive_freedom/e300/Kconfig.defconfig.e340 @@ -0,0 +1,5 @@ +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +config SOC + default "e340" if SOC_SIFIVE_FREEDOM_E340 diff --git a/soc/riscv/riscv-privileged/sifive-freedom/Kconfig.defconfig.series b/soc/riscv/sifive_freedom/e300/Kconfig.defconfig.series similarity index 65% rename from soc/riscv/riscv-privileged/sifive-freedom/Kconfig.defconfig.series rename to soc/riscv/sifive_freedom/e300/Kconfig.defconfig.series index 0c3cd5417734990..b2f16e5261de871 100644 --- a/soc/riscv/riscv-privileged/sifive-freedom/Kconfig.defconfig.series +++ b/soc/riscv/sifive_freedom/e300/Kconfig.defconfig.series @@ -1,9 +1,10 @@ +# Copyright (c) 2017 Jean-Paul Etienne # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_RISCV_SIFIVE_FREEDOM +if SOC_SERIES_SIFIVE_FREEDOM_E300 config SOC_SERIES - default "sifive-freedom" + default "e300" config SYS_CLOCK_HW_CYCLES_PER_SEC default 32768 @@ -32,4 +33,6 @@ config MAX_IRQ_PER_AGGREGATOR config NUM_IRQS default 64 -endif # SOC_SERIES_RISCV_SIFIVE_FREEDOM +source "soc/riscv/sifive_freedom/e300/Kconfig.defconfig.e*" + +endif # SOC_SERIES_SIFIVE_FREEDOM_E300 diff --git a/soc/riscv/sifive_freedom/e300/Kconfig.series b/soc/riscv/sifive_freedom/e300/Kconfig.series new file mode 100644 index 000000000000000..47ae89e6d4cd022 --- /dev/null +++ b/soc/riscv/sifive_freedom/e300/Kconfig.series @@ -0,0 +1,12 @@ +# RISCV_SIFIVE_FREEDOM SOC implementation + +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_SIFIVE_FREEDOM_E300 + bool "SiFive Freedom E300 SOC implementation" + select RISCV + select RISCV_PRIVILEGED + select SOC_FAMILY_SIFIVE_FREEDOM + help + Enable support for SiFive Freedom FE300 SOC diff --git a/soc/riscv/sifive_freedom/e300/Kconfig.soc b/soc/riscv/sifive_freedom/e300/Kconfig.soc new file mode 100644 index 000000000000000..e53b84c08907d11 --- /dev/null +++ b/soc/riscv/sifive_freedom/e300/Kconfig.soc @@ -0,0 +1,20 @@ +# RISCV_SIFIVE_FREEDOM SOC configuration options + +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "SiFive Freedom SOC implementation" + depends on SOC_SERIES_SIFIVE_FREEDOM_E300 + +config SOC_SIFIVE_FREEDOM_E340 + bool "SiFive Freedom SOC implementation" + select ATOMIC_OPERATIONS_C + select INCLUDE_RESET_VECTOR + select RISCV_ISA_RV32I + select RISCV_ISA_EXT_M + select RISCV_ISA_EXT_A + select RISCV_ISA_EXT_ZICSR + select RISCV_ISA_EXT_ZIFENCEI + +endchoice diff --git a/soc/riscv/riscv-privileged/sifive-freedom/fe310_clock.c b/soc/riscv/sifive_freedom/e300/clock.c similarity index 98% rename from soc/riscv/riscv-privileged/sifive-freedom/fe310_clock.c rename to soc/riscv/sifive_freedom/e300/clock.c index 0b642f3e8b2203f..8fde8121db95fb7 100644 --- a/soc/riscv/riscv-privileged/sifive-freedom/fe310_clock.c +++ b/soc/riscv/sifive_freedom/e300/clock.c @@ -7,7 +7,7 @@ #include #include -#include "fe310_prci.h" +#include "prci.h" #define CORECLK_HZ (DT_PROP(DT_NODELABEL(coreclk), clock_frequency)) BUILD_ASSERT(DT_PROP(DT_NODELABEL(tlclk), clock_div) == 1, diff --git a/soc/riscv/riscv-privileged/sifive-freedom/fe310_prci.h b/soc/riscv/sifive_freedom/e300/prci.h similarity index 100% rename from soc/riscv/riscv-privileged/sifive-freedom/fe310_prci.h rename to soc/riscv/sifive_freedom/e300/prci.h diff --git a/soc/riscv/riscv-privileged/sifive-freedom/soc.h b/soc/riscv/sifive_freedom/e300/soc.h similarity index 52% rename from soc/riscv/riscv-privileged/sifive-freedom/soc.h rename to soc/riscv/sifive_freedom/e300/soc.h index 958891a9d6a1ec3..c83f5f322b60025 100644 --- a/soc/riscv/riscv-privileged/sifive-freedom/soc.h +++ b/soc/riscv/sifive_freedom/e300/soc.h @@ -8,30 +8,17 @@ * @file SoC configuration macros for the SiFive Freedom processor */ -#ifndef __RISCV_SIFIVE_FREEDOM_SOC_H_ -#define __RISCV_SIFIVE_FREEDOM_SOC_H_ +#ifndef __RISCV_SIFIVE_FREEDOM_FE300_SOC_H_ +#define __RISCV_SIFIVE_FREEDOM_FE300_SOC_H_ #include -#if defined(CONFIG_SOC_RISCV_SIFIVE_FREEDOM) /* PINMUX MAX PINS */ #define SIFIVE_PINMUX_PINS 32 /* Clock controller. */ #define PRCI_BASE_ADDR 0x10008000 -#elif defined(CONFIG_SOC_RISCV_SIFIVE_FU540) || defined(CONFIG_SOC_RISCV_SIFIVE_FU740) - -/* Clock controller. */ -#define PRCI_BASE_ADDR 0x10000000 - -/* PINMUX MAX PINS */ -#define SIFIVE_PINMUX_PINS 16 - -#endif - -#if defined(CONFIG_SOC_RISCV_SIFIVE_FREEDOM) || defined(CONFIG_SOC_RISCV_SIFIVE_FU540) - /* * On FE310 and FU540, peripherals such as SPI, UART, I2C and PWM are clocked * by TLCLK, which is derived from CORECLK. @@ -42,12 +29,4 @@ #define SIFIVE_PERIPHERAL_CLOCK_FREQUENCY \ (SIFIVE_TLCLK_BASE_FREQUENCY / SIFIVE_TLCLK_DIVIDER) -#elif defined(CONFIG_SOC_RISCV_SIFIVE_FU740) - -/* On FU740, peripherals are clocked by PCLK. */ -#define SIFIVE_PERIPHERAL_CLOCK_FREQUENCY \ - DT_PROP(DT_NODELABEL(pclk), clock_frequency) - -#endif - -#endif /* __RISCV_SIFIVE_FREEDOM_SOC_H_ */ +#endif /* __RISCV_SIFIVE_FREEDOM_FE300_SOC_H_ */ diff --git a/soc/riscv/sifive_freedom/u500/CMakeLists.txt b/soc/riscv/sifive_freedom/u500/CMakeLists.txt new file mode 100644 index 000000000000000..baf01a6b0473772 --- /dev/null +++ b/soc/riscv/sifive_freedom/u500/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources(clock.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/sifive_freedom/u500/Kconfig.defconfig.series b/soc/riscv/sifive_freedom/u500/Kconfig.defconfig.series new file mode 100644 index 000000000000000..d6b946786864d55 --- /dev/null +++ b/soc/riscv/sifive_freedom/u500/Kconfig.defconfig.series @@ -0,0 +1,38 @@ +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_SIFIVE_FREEDOM_U500 + +config SOC_SERIES + default "u500" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 32768 + +config RISCV_SOC_INTERRUPT_INIT + default y + +config RISCV_HAS_CPU_IDLE + default y + +config RISCV_HAS_PLIC + default y + +config RISCV_GP + default y + +config 2ND_LVL_ISR_TBL_OFFSET + default 12 + +config 2ND_LVL_INTR_00_OFFSET + default 11 + +config MAX_IRQ_PER_AGGREGATOR + default 52 + +config NUM_IRQS + default 64 + +source "soc/riscv/sifive_freedom/u500/Kconfig.defconfig.u*" + +endif # SOC_SERIES_SIFIVE_FREEDOM_U500 diff --git a/soc/riscv/sifive_freedom/u500/Kconfig.defconfig.u540 b/soc/riscv/sifive_freedom/u500/Kconfig.defconfig.u540 new file mode 100644 index 000000000000000..f559f5914b3f094 --- /dev/null +++ b/soc/riscv/sifive_freedom/u500/Kconfig.defconfig.u540 @@ -0,0 +1,5 @@ +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +config SOC + default "u540" if SOC_SIFIVE_FREEDOM_U540 diff --git a/soc/riscv/sifive_freedom/u500/Kconfig.series b/soc/riscv/sifive_freedom/u500/Kconfig.series new file mode 100644 index 000000000000000..a576dfbc6f7a54b --- /dev/null +++ b/soc/riscv/sifive_freedom/u500/Kconfig.series @@ -0,0 +1,12 @@ +# RISCV_SIFIVE_FREEDOM SOC implementation + +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_SIFIVE_FREEDOM_U500 + bool "SiFive Freedom U500 SOC implementation" + select RISCV + select RISCV_PRIVILEGED + select SOC_FAMILY_SIFIVE_FREEDOM + help + Enable support for SiFive Freedom U500 SOC diff --git a/soc/riscv/sifive_freedom/u500/Kconfig.soc b/soc/riscv/sifive_freedom/u500/Kconfig.soc new file mode 100644 index 000000000000000..0a88ccf8cc1ffd8 --- /dev/null +++ b/soc/riscv/sifive_freedom/u500/Kconfig.soc @@ -0,0 +1,22 @@ +# RISCV_SIFIVE_FREEDOM SOC configuration options + +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "SiFive Freedom SOC implementation" + depends on SOC_SERIES_SIFIVE_FREEDOM_U500 + +config SOC_SIFIVE_FREEDOM_U540 + bool "SiFive Freedom U540 SOC implementation" + select ATOMIC_OPERATIONS_C + select INCLUDE_RESET_VECTOR + select 64BIT + select RISCV_ISA_RV64I + select RISCV_ISA_EXT_M + select RISCV_ISA_EXT_A + select RISCV_ISA_EXT_C + select RISCV_ISA_EXT_ZICSR + select RISCV_ISA_EXT_ZIFENCEI + +endchoice diff --git a/soc/riscv/riscv-privileged/sifive-freedom/fu540_clock.c b/soc/riscv/sifive_freedom/u500/clock.c similarity index 97% rename from soc/riscv/riscv-privileged/sifive-freedom/fu540_clock.c rename to soc/riscv/sifive_freedom/u500/clock.c index bc68a502f5989d4..87929892f77d083 100644 --- a/soc/riscv/riscv-privileged/sifive-freedom/fu540_clock.c +++ b/soc/riscv/sifive_freedom/u500/clock.c @@ -7,7 +7,7 @@ #include #include #include -#include "fu540_prci.h" +#include "prci.h" BUILD_ASSERT(MHZ(1000) == DT_PROP(DT_NODELABEL(coreclk), clock_frequency), "Unsupported CORECLK frequency"); diff --git a/soc/riscv/riscv-privileged/sifive-freedom/fu540_prci.h b/soc/riscv/sifive_freedom/u500/prci.h similarity index 100% rename from soc/riscv/riscv-privileged/sifive-freedom/fu540_prci.h rename to soc/riscv/sifive_freedom/u500/prci.h diff --git a/soc/riscv/sifive_freedom/u500/soc.h b/soc/riscv/sifive_freedom/u500/soc.h new file mode 100644 index 000000000000000..ed367950278cdc3 --- /dev/null +++ b/soc/riscv/sifive_freedom/u500/soc.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 Jean-Paul Etienne + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file SoC configuration macros for the SiFive Freedom processor + */ + +#ifndef __RISCV_SIFIVE_FREEDOM_U500_SOC_H_ +#define __RISCV_SIFIVE_FREEDOM_U500_SOC_H_ + +#include + +/* Clock controller. */ +#define PRCI_BASE_ADDR 0x10000000 + +/* PINMUX MAX PINS */ +#define SIFIVE_PINMUX_PINS 16 + +/* + * On FE310 and FU540, peripherals such as SPI, UART, I2C and PWM are clocked + * by TLCLK, which is derived from CORECLK. + */ +#define SIFIVE_TLCLK_BASE_FREQUENCY \ + DT_PROP_BY_PHANDLE_IDX(DT_NODELABEL(tlclk), clocks, 0, clock_frequency) +#define SIFIVE_TLCLK_DIVIDER DT_PROP(DT_NODELABEL(tlclk), clock_div) +#define SIFIVE_PERIPHERAL_CLOCK_FREQUENCY \ + (SIFIVE_TLCLK_BASE_FREQUENCY / SIFIVE_TLCLK_DIVIDER) + +#endif /* __RISCV_SIFIVE_FREEDOM_U500_SOC_H_ */ diff --git a/soc/riscv/sifive_freedom/u700/CMakeLists.txt b/soc/riscv/sifive_freedom/u700/CMakeLists.txt new file mode 100644 index 000000000000000..baf01a6b0473772 --- /dev/null +++ b/soc/riscv/sifive_freedom/u700/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources(clock.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/riscv/sifive_freedom/u700/Kconfig.defconfig.series b/soc/riscv/sifive_freedom/u700/Kconfig.defconfig.series new file mode 100644 index 000000000000000..347ac14b551f993 --- /dev/null +++ b/soc/riscv/sifive_freedom/u700/Kconfig.defconfig.series @@ -0,0 +1,38 @@ +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_SIFIVE_FREEDOM_U700 + +config SOC_SERIES + default "u700" + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 32768 + +config RISCV_SOC_INTERRUPT_INIT + default y + +config RISCV_HAS_CPU_IDLE + default y + +config RISCV_HAS_PLIC + default y + +config RISCV_GP + default y + +config 2ND_LVL_ISR_TBL_OFFSET + default 12 + +config 2ND_LVL_INTR_00_OFFSET + default 11 + +config MAX_IRQ_PER_AGGREGATOR + default 52 + +config NUM_IRQS + default 64 + +source "soc/riscv/sifive_freedom/u700/Kconfig.defconfig.u*" + +endif # SOC_SERIES_SIFIVE_FREEDOM_U700 diff --git a/soc/riscv/sifive_freedom/u700/Kconfig.defconfig.u740 b/soc/riscv/sifive_freedom/u700/Kconfig.defconfig.u740 new file mode 100644 index 000000000000000..ca935f772eb0021 --- /dev/null +++ b/soc/riscv/sifive_freedom/u700/Kconfig.defconfig.u740 @@ -0,0 +1,5 @@ +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +config SOC + default "u740" if SOC_SIFIVE_FREEDOM_U740 diff --git a/soc/riscv/sifive_freedom/u700/Kconfig.series b/soc/riscv/sifive_freedom/u700/Kconfig.series new file mode 100644 index 000000000000000..613844703c76234 --- /dev/null +++ b/soc/riscv/sifive_freedom/u700/Kconfig.series @@ -0,0 +1,12 @@ +# RISCV_SIFIVE_FREEDOM SOC implementation + +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_SIFIVE_FREEDOM_U700 + bool "SiFive Freedom SOC U700 implementation" + select RISCV + select RISCV_PRIVILEGED + select SOC_FAMILY_SIFIVE_FREEDOM + help + Enable support for SiFive Freedom U700 SOC diff --git a/soc/riscv/sifive_freedom/u700/Kconfig.soc b/soc/riscv/sifive_freedom/u700/Kconfig.soc new file mode 100644 index 000000000000000..1eec9b4bb17a715 --- /dev/null +++ b/soc/riscv/sifive_freedom/u700/Kconfig.soc @@ -0,0 +1,22 @@ +# RISCV_SIFIVE_FREEDOM SOC configuration options + +# Copyright (c) 2017 Jean-Paul Etienne +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "SiFive Freedom SOC implementation" + depends on SOC_SERIES_SIFIVE_FREEDOM_U700 + +config SOC_SIFIVE_FREEDOM_U740 + bool "SiFive Freedom U740 SOC implementation" + select ATOMIC_OPERATIONS_C + select INCLUDE_RESET_VECTOR + select 64BIT + select RISCV_ISA_RV64I + select RISCV_ISA_EXT_M + select RISCV_ISA_EXT_A + select RISCV_ISA_EXT_C + select RISCV_ISA_EXT_ZICSR + select RISCV_ISA_EXT_ZIFENCEI + +endchoice diff --git a/soc/riscv/riscv-privileged/sifive-freedom/fu740_clock.c b/soc/riscv/sifive_freedom/u700/clock.c similarity index 99% rename from soc/riscv/riscv-privileged/sifive-freedom/fu740_clock.c rename to soc/riscv/sifive_freedom/u700/clock.c index e6bbee93689f7bf..5c3fa5673432bc1 100644 --- a/soc/riscv/riscv-privileged/sifive-freedom/fu740_clock.c +++ b/soc/riscv/sifive_freedom/u700/clock.c @@ -8,7 +8,7 @@ #include #include -#include "fu740_prci.h" +#include "prci.h" BUILD_ASSERT(MHZ(1000) == DT_PROP(DT_NODELABEL(coreclk), clock_frequency), "Unsupported CORECLK frequency"); diff --git a/soc/riscv/riscv-privileged/sifive-freedom/fu740_prci.h b/soc/riscv/sifive_freedom/u700/prci.h similarity index 100% rename from soc/riscv/riscv-privileged/sifive-freedom/fu740_prci.h rename to soc/riscv/sifive_freedom/u700/prci.h diff --git a/soc/riscv/sifive_freedom/u700/soc.h b/soc/riscv/sifive_freedom/u700/soc.h new file mode 100644 index 000000000000000..91aac61afddd712 --- /dev/null +++ b/soc/riscv/sifive_freedom/u700/soc.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017 Jean-Paul Etienne + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file SoC configuration macros for the SiFive Freedom processor + */ + +#ifndef __RISCV_SIFIVE_FREEDOM_U700_SOC_H_ +#define __RISCV_SIFIVE_FREEDOM_U700_SOC_H_ + +#include + +/* Clock controller. */ +#define PRCI_BASE_ADDR 0x10000000 + +/* PINMUX MAX PINS */ +#define SIFIVE_PINMUX_PINS 16 + +/* On FU740, peripherals are clocked by PCLK. */ +#define SIFIVE_PERIPHERAL_CLOCK_FREQUENCY \ + DT_PROP(DT_NODELABEL(pclk), clock_frequency) + +#endif /* __RISCV_SIFIVE_FREEDOM_U700_SOC_H_ */ diff --git a/soc/riscv/starfive_jh71xx/CMakeLists.txt b/soc/riscv/starfive_jh71xx/CMakeLists.txt new file mode 100644 index 000000000000000..69b2926358e5cf8 --- /dev/null +++ b/soc/riscv/starfive_jh71xx/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(${SOC_SERIES}) diff --git a/soc/riscv/starfive_jh71xx/Kconfig b/soc/riscv/starfive_jh71xx/Kconfig new file mode 100644 index 000000000000000..65694c07eff78ff --- /dev/null +++ b/soc/riscv/starfive_jh71xx/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_STARFIVE_JH71XX + bool + +if SOC_FAMILY_STARFIVE_JH71XX + +config SOC_FAMILY + string + default "starfive_jh71xx" + +source "soc/riscv/starfive_jh71xx/*/Kconfig.soc" + +endif # SOC_FAMILY_STARFIVE_JH71XX diff --git a/soc/riscv/starfive_jh71xx/Kconfig.defconfig b/soc/riscv/starfive_jh71xx/Kconfig.defconfig new file mode 100644 index 000000000000000..b399e38b3406df0 --- /dev/null +++ b/soc/riscv/starfive_jh71xx/Kconfig.defconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/starfive_jh71xx/*/Kconfig.defconfig.series" diff --git a/soc/riscv/starfive_jh71xx/Kconfig.soc b/soc/riscv/starfive_jh71xx/Kconfig.soc new file mode 100644 index 000000000000000..1ff54faa97013dc --- /dev/null +++ b/soc/riscv/starfive_jh71xx/Kconfig.soc @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/starfive_jh71xx/*/Kconfig.series" diff --git a/soc/riscv/riscv-privileged/starfive_jh71xx/CMakeLists.txt b/soc/riscv/starfive_jh71xx/jh71xx/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/starfive_jh71xx/CMakeLists.txt rename to soc/riscv/starfive_jh71xx/jh71xx/CMakeLists.txt diff --git a/soc/riscv/starfive_jh71xx/jh71xx/Kconfig.defconfig.jh7100 b/soc/riscv/starfive_jh71xx/jh71xx/Kconfig.defconfig.jh7100 new file mode 100644 index 000000000000000..6f38d61dd4e5ce8 --- /dev/null +++ b/soc/riscv/starfive_jh71xx/jh71xx/Kconfig.defconfig.jh7100 @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC + default "jh7100" if SOC_JH7100 diff --git a/soc/riscv/riscv-privileged/starfive_jh71xx/Kconfig.defconfig.series b/soc/riscv/starfive_jh71xx/jh71xx/Kconfig.defconfig.series similarity index 84% rename from soc/riscv/riscv-privileged/starfive_jh71xx/Kconfig.defconfig.series rename to soc/riscv/starfive_jh71xx/jh71xx/Kconfig.defconfig.series index c488c614b7d2f08..77436b593e14098 100644 --- a/soc/riscv/riscv-privileged/starfive_jh71xx/Kconfig.defconfig.series +++ b/soc/riscv/starfive_jh71xx/jh71xx/Kconfig.defconfig.series @@ -4,7 +4,7 @@ if SOC_SERIES_STARFIVE_JH71XX config SOC_SERIES - default "starfive_jh71xx" + default "jh71xx" config SYS_CLOCK_HW_CYCLES_PER_SEC default 6250000 @@ -30,4 +30,6 @@ config 2ND_LVL_INTR_00_OFFSET config NUM_IRQS default 139 +source "soc/riscv/starfive_jh71xx/jh71xx/Kconfig.defconfig.jh71*" + endif diff --git a/soc/riscv/riscv-privileged/starfive_jh71xx/Kconfig.series b/soc/riscv/starfive_jh71xx/jh71xx/Kconfig.series similarity index 86% rename from soc/riscv/riscv-privileged/starfive_jh71xx/Kconfig.series rename to soc/riscv/starfive_jh71xx/jh71xx/Kconfig.series index b360f78b77b413b..19cedcefe270f3e 100644 --- a/soc/riscv/riscv-privileged/starfive_jh71xx/Kconfig.series +++ b/soc/riscv/starfive_jh71xx/jh71xx/Kconfig.series @@ -4,6 +4,6 @@ config SOC_SERIES_STARFIVE_JH71XX bool "Starfive JH71XX series" select RISCV - select SOC_FAMILY_RISCV_PRIVILEGED + select RISCV_PRIVILEGED help Enable support for Starfive JH71XX SoC Series. diff --git a/soc/riscv/riscv-privileged/starfive_jh71xx/Kconfig.soc b/soc/riscv/starfive_jh71xx/jh71xx/Kconfig.soc similarity index 100% rename from soc/riscv/riscv-privileged/starfive_jh71xx/Kconfig.soc rename to soc/riscv/starfive_jh71xx/jh71xx/Kconfig.soc diff --git a/soc/riscv/riscv-privileged/starfive_jh71xx/soc.h b/soc/riscv/starfive_jh71xx/jh71xx/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/starfive_jh71xx/soc.h rename to soc/riscv/starfive_jh71xx/jh71xx/soc.h diff --git a/soc/riscv/telink_tlsr/CMakeLists.txt b/soc/riscv/telink_tlsr/CMakeLists.txt new file mode 100644 index 000000000000000..69b2926358e5cf8 --- /dev/null +++ b/soc/riscv/telink_tlsr/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(${SOC_SERIES}) diff --git a/soc/riscv/telink_tlsr/Kconfig b/soc/riscv/telink_tlsr/Kconfig new file mode 100644 index 000000000000000..144751311ba963f --- /dev/null +++ b/soc/riscv/telink_tlsr/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_TELINK_TLSR + bool + +if SOC_FAMILY_TELINK_TLSR + +config SOC_FAMILY + string + default "telink_tlsr" + +source "soc/riscv/telink_tlsr/*/Kconfig.soc" + +endif # SOC_FAMILY_TELINK_TLSR diff --git a/soc/riscv/telink_tlsr/Kconfig.defconfig b/soc/riscv/telink_tlsr/Kconfig.defconfig new file mode 100644 index 000000000000000..04a888381fa9c1d --- /dev/null +++ b/soc/riscv/telink_tlsr/Kconfig.defconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/telink_tlsr/*/Kconfig.defconfig.series" diff --git a/soc/riscv/telink_tlsr/Kconfig.soc b/soc/riscv/telink_tlsr/Kconfig.soc new file mode 100644 index 000000000000000..db09c69d1f4ec0f --- /dev/null +++ b/soc/riscv/telink_tlsr/Kconfig.soc @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/riscv/telink_tlsr/*/Kconfig.series" diff --git a/soc/riscv/riscv-privileged/telink_b91/CMakeLists.txt b/soc/riscv/telink_tlsr/tlsr951x/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/CMakeLists.txt rename to soc/riscv/telink_tlsr/tlsr951x/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/telink_b91/Kconfig.defconfig.series b/soc/riscv/telink_tlsr/tlsr951x/Kconfig.defconfig.series similarity index 81% rename from soc/riscv/riscv-privileged/telink_b91/Kconfig.defconfig.series rename to soc/riscv/telink_tlsr/tlsr951x/Kconfig.defconfig.series index 986b62407505e92..23a78c9f0da66ec 100644 --- a/soc/riscv/riscv-privileged/telink_b91/Kconfig.defconfig.series +++ b/soc/riscv/telink_tlsr/tlsr951x/Kconfig.defconfig.series @@ -1,11 +1,11 @@ # Copyright (c) 2021 Telink Semiconductor # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_RISCV_TELINK_B91 +if SOC_SERIES_TELINK_TLSR951X config SOC_SERIES string - default "telink_b91" + default "tlsr951x" config SYS_CLOCK_HW_CYCLES_PER_SEC int @@ -56,4 +56,6 @@ config 2ND_LVL_INTR_00_OFFSET config HAS_FLASH_LOAD_OFFSET default y if BOOTLOADER_MCUBOOT -endif # SOC_SERIES_RISCV_TELINK_B91 +source "soc/riscv/telink_tlsr/tlsr951x/Kconfig.defconfig.tlsr*" + +endif # SOC_SERIES_TELINK_TLSR951X diff --git a/soc/riscv/telink_tlsr/tlsr951x/Kconfig.defconfig.tlsr9518 b/soc/riscv/telink_tlsr/tlsr951x/Kconfig.defconfig.tlsr9518 new file mode 100644 index 000000000000000..4ffdebdaf6b6ec4 --- /dev/null +++ b/soc/riscv/telink_tlsr/tlsr951x/Kconfig.defconfig.tlsr9518 @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC + default "tlsr9518" if SOC_TELINK_TLSR9518 diff --git a/soc/riscv/riscv-privileged/telink_b91/Kconfig.series b/soc/riscv/telink_tlsr/tlsr951x/Kconfig.series similarity index 54% rename from soc/riscv/riscv-privileged/telink_b91/Kconfig.series rename to soc/riscv/telink_tlsr/tlsr951x/Kconfig.series index a966dfe447bd993..5ad3053725e29c3 100644 --- a/soc/riscv/riscv-privileged/telink_b91/Kconfig.series +++ b/soc/riscv/telink_tlsr/tlsr951x/Kconfig.series @@ -1,8 +1,8 @@ # Copyright (c) 2021 Telink Semiconductor # SPDX-License-Identifier: Apache-2.0 -config SOC_SERIES_RISCV_TELINK_B91 - bool "Telink B91 SoC Implementation" +config SOC_SERIES_TELINK_TLSR951X + bool "Telink TLSR951X" select RISCV select RISCV_ISA_RV32I select RISCV_ISA_EXT_M @@ -10,7 +10,11 @@ config SOC_SERIES_RISCV_TELINK_B91 select RISCV_ISA_EXT_C select RISCV_ISA_EXT_ZICSR select RISCV_ISA_EXT_ZIFENCEI - select SOC_FAMILY_RISCV_PRIVILEGED + select RISCV_PRIVILEGED select HAS_TELINK_DRIVERS + select ATOMIC_OPERATIONS_BUILTIN + select CPU_HAS_FPU + select INCLUDE_RESET_VECTOR + select SOC_FAMILY_TELINK_TLSR help - Enable support for Telink B91 SoC + Enable support for Telink TLSR951X diff --git a/soc/riscv/telink_tlsr/tlsr951x/Kconfig.soc b/soc/riscv/telink_tlsr/tlsr951x/Kconfig.soc new file mode 100644 index 000000000000000..2abc12cc58c5b7a --- /dev/null +++ b/soc/riscv/telink_tlsr/tlsr951x/Kconfig.soc @@ -0,0 +1,23 @@ +# Copyright (c) 2021 Telink Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_TELINK_TLSR951X + +choice + prompt "Telink TLSR951X SoC implementation" + +config SOC_TELINK_TLSR9518 + bool "Telink TLSR9518" + +endchoice + +config TELINK_B91_HWDSP + bool "Support Hardware DSP" + select RISCV_SOC_CONTEXT_SAVE + +config TELINK_B91_PFT_ARCH + bool "Support performance throttling" + default y + select RISCV_SOC_CONTEXT_SAVE + +endif # SOC_SERIES_TELINK_TLSR951X diff --git a/soc/riscv/riscv-privileged/telink_b91/init.ld b/soc/riscv/telink_tlsr/tlsr951x/init.ld similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/init.ld rename to soc/riscv/telink_tlsr/tlsr951x/init.ld diff --git a/soc/riscv/riscv-privileged/telink_b91/linker.ld b/soc/riscv/telink_tlsr/tlsr951x/linker.ld similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/linker.ld rename to soc/riscv/telink_tlsr/tlsr951x/linker.ld diff --git a/soc/riscv/riscv-privileged/telink_b91/pinctrl_soc.h b/soc/riscv/telink_tlsr/tlsr951x/pinctrl_soc.h similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/pinctrl_soc.h rename to soc/riscv/telink_tlsr/tlsr951x/pinctrl_soc.h diff --git a/soc/riscv/riscv-privileged/telink_b91/soc.c b/soc/riscv/telink_tlsr/tlsr951x/soc.c similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/soc.c rename to soc/riscv/telink_tlsr/tlsr951x/soc.c diff --git a/soc/riscv/riscv-privileged/telink_b91/soc.h b/soc/riscv/telink_tlsr/tlsr951x/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/soc.h rename to soc/riscv/telink_tlsr/tlsr951x/soc.h diff --git a/soc/riscv/riscv-privileged/telink_b91/soc_context.h b/soc/riscv/telink_tlsr/tlsr951x/soc_context.h similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/soc_context.h rename to soc/riscv/telink_tlsr/tlsr951x/soc_context.h diff --git a/soc/riscv/riscv-privileged/telink_b91/soc_irq.S b/soc/riscv/telink_tlsr/tlsr951x/soc_irq.S similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/soc_irq.S rename to soc/riscv/telink_tlsr/tlsr951x/soc_irq.S diff --git a/soc/riscv/riscv-privileged/telink_b91/soc_offsets.h b/soc/riscv/telink_tlsr/tlsr951x/soc_offsets.h similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/soc_offsets.h rename to soc/riscv/telink_tlsr/tlsr951x/soc_offsets.h diff --git a/soc/riscv/riscv-privileged/telink_b91/start.S b/soc/riscv/telink_tlsr/tlsr951x/start.S similarity index 100% rename from soc/riscv/riscv-privileged/telink_b91/start.S rename to soc/riscv/telink_tlsr/tlsr951x/start.S diff --git a/soc/riscv/riscv-privileged/virt/CMakeLists.txt b/soc/riscv/virt/CMakeLists.txt similarity index 100% rename from soc/riscv/riscv-privileged/virt/CMakeLists.txt rename to soc/riscv/virt/CMakeLists.txt diff --git a/soc/riscv/riscv-privileged/virt/Kconfig.defconfig.series b/soc/riscv/virt/Kconfig.defconfig similarity index 91% rename from soc/riscv/riscv-privileged/virt/Kconfig.defconfig.series rename to soc/riscv/virt/Kconfig.defconfig index 231d4519d6771e9..9773586e922b70a 100644 --- a/soc/riscv/riscv-privileged/virt/Kconfig.defconfig.series +++ b/soc/riscv/virt/Kconfig.defconfig @@ -1,9 +1,9 @@ # Copyright (c) 2020 Cobham Gaisler AB # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_RISCV_VIRT +if SOC_RISCV_VIRT -config SOC_SERIES +config SOC default "virt" config SYS_CLOCK_HW_CYCLES_PER_SEC diff --git a/soc/riscv/riscv-privileged/virt/Kconfig.soc b/soc/riscv/virt/Kconfig.soc similarity index 75% rename from soc/riscv/riscv-privileged/virt/Kconfig.soc rename to soc/riscv/virt/Kconfig.soc index 35a2853eb50089a..9a9168f5a8c4f26 100644 --- a/soc/riscv/riscv-privileged/virt/Kconfig.soc +++ b/soc/riscv/virt/Kconfig.soc @@ -1,10 +1,6 @@ # Copyright (c) 2020 Cobham Gaisler AB # SPDX-License-Identifier: Apache-2.0 -choice - prompt "QEMU RISC-V VirtIO Board" - depends on SOC_SERIES_RISCV_VIRT - config SOC_RISCV_VIRT bool "QEMU RISC-V VirtIO Board" select ATOMIC_OPERATIONS_BUILTIN @@ -12,5 +8,5 @@ config SOC_RISCV_VIRT select RISCV_ISA_EXT_M select RISCV_ISA_EXT_A select RISCV_ISA_EXT_C - -endchoice + select RISCV + select RISCV_PRIVILEGED diff --git a/soc/riscv/riscv-privileged/virt/soc.c b/soc/riscv/virt/soc.c similarity index 100% rename from soc/riscv/riscv-privileged/virt/soc.c rename to soc/riscv/virt/soc.c diff --git a/soc/riscv/riscv-privileged/virt/soc.h b/soc/riscv/virt/soc.h similarity index 100% rename from soc/riscv/riscv-privileged/virt/soc.h rename to soc/riscv/virt/soc.h diff --git a/soc/xtensa/espressif_esp32/esp32/default.ld b/soc/xtensa/espressif_esp32/esp32/default.ld index 20dc3c28ef57998..7a78c49f36482ae 100644 --- a/soc/xtensa/espressif_esp32/esp32/default.ld +++ b/soc/xtensa/espressif_esp32/esp32/default.ld @@ -203,14 +203,8 @@ SECTIONS *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) *(.rodata_wlog) *(.rodata_wlog*) - _thread_local_end = ABSOLUTE(.); . = ALIGN(4); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) @@ -221,6 +215,7 @@ SECTIONS #include #include #include + #include #include /* Create an explicit section at the end of all the data that shall be mapped into drom. diff --git a/soc/xtensa/espressif_esp32/esp32s2/default.ld b/soc/xtensa/espressif_esp32/esp32s2/default.ld index 15f654d4b99f586..8a78bb89ac2d1e9 100644 --- a/soc/xtensa/espressif_esp32/esp32s2/default.ld +++ b/soc/xtensa/espressif_esp32/esp32s2/default.ld @@ -175,14 +175,8 @@ SECTIONS *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) *(.rodata_wlog) *(.rodata_wlog*) - _thread_local_end = ABSOLUTE(.); . = ALIGN(4); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) @@ -192,6 +186,7 @@ SECTIONS #include #include #include + #include #include /* Create an explicit section at the end of all the data that shall be mapped into drom. diff --git a/soc/xtensa/espressif_esp32/esp32s3/default.ld b/soc/xtensa/espressif_esp32/esp32s3/default.ld index 90b6c89ada2a08b..4076ea7c1af13ee 100644 --- a/soc/xtensa/espressif_esp32/esp32s3/default.ld +++ b/soc/xtensa/espressif_esp32/esp32s3/default.ld @@ -211,14 +211,8 @@ SECTIONS *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) *(.rodata_wlog) *(.rodata_wlog*) - _thread_local_end = ABSOLUTE(.); . = ALIGN(4); } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) @@ -229,6 +223,7 @@ SECTIONS #include #include #include + #include #include /* Create an explicit section at the end of all the data that shall be mapped into drom. diff --git a/soc/xtensa/intel_adsp/common/ipc.c b/soc/xtensa/intel_adsp/common/ipc.c index cdb5757d3560473..6ae1956ffac3892 100644 --- a/soc/xtensa/intel_adsp/common/ipc.c +++ b/soc/xtensa/intel_adsp/common/ipc.c @@ -82,7 +82,6 @@ void z_intel_adsp_ipc_isr(const void *devarg) } regs->ida = INTEL_ADSP_IPC_DONE; - pm_device_busy_clear(dev); } k_spin_unlock(&devdata->lock, key); @@ -163,6 +162,7 @@ int intel_adsp_ipc_send_message(const struct device *dev, config->regs->idd = ext_data; config->regs->idr = data | INTEL_ADSP_IPC_BUSY; k_spin_unlock(&devdata->lock, key); + pm_device_busy_clear(dev); return 0; } diff --git a/subsys/bluetooth/Kconfig.logging b/subsys/bluetooth/Kconfig.logging index 5a7032723fca914..c103a42c31656ec 100644 --- a/subsys/bluetooth/Kconfig.logging +++ b/subsys/bluetooth/Kconfig.logging @@ -846,6 +846,12 @@ legacy-debug-sym = BT_DEBUG_VOCS_CLIENT module-str = "Volume Offset Control Service client" source "subsys/bluetooth/common/Kconfig.template.log_config_bt" +# PBP + +module = BT_PBP +module-str = "Public Broadcast Profile" +source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" + endmenu # Audio menu "Others" diff --git a/subsys/bluetooth/audio/CMakeLists.txt b/subsys/bluetooth/audio/CMakeLists.txt index 26185111ce98956..293498fbd404a1d 100644 --- a/subsys/bluetooth/audio/CMakeLists.txt +++ b/subsys/bluetooth/audio/CMakeLists.txt @@ -67,3 +67,4 @@ if (CONFIG_BT_CAP_INITIATOR OR CONFIG_BT_CAP_COMMANDER) endif() zephyr_library_sources_ifdef(CONFIG_BT_TMAP tmap.c) zephyr_library_sources_ifdef(CONFIG_BT_GMAP gmap_client.c gmap_server.c) +zephyr_library_sources_ifdef(CONFIG_BT_PBP pbp.c) diff --git a/subsys/bluetooth/audio/Kconfig b/subsys/bluetooth/audio/Kconfig index d720b0952231de1..b60475c02e26611 100644 --- a/subsys/bluetooth/audio/Kconfig +++ b/subsys/bluetooth/audio/Kconfig @@ -61,6 +61,7 @@ rsource "Kconfig.mctl" rsource "Kconfig.cap" rsource "Kconfig.tmap" rsource "Kconfig.gmap" +rsource "Kconfig.pbp" module = BT_AUDIO module-str = "Bluetooth Audio" diff --git a/subsys/bluetooth/audio/Kconfig.pbp b/subsys/bluetooth/audio/Kconfig.pbp new file mode 100644 index 000000000000000..cb24845b202b752 --- /dev/null +++ b/subsys/bluetooth/audio/Kconfig.pbp @@ -0,0 +1,12 @@ +# Bluetooth Audio - Public Broadcast Profile (PBP) options +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +config BT_PBP + bool "Public Broadcast Profile [EXPERIMENTAL]" + select EXPERIMENTAL + help + Enabling this will enable PBP. diff --git a/subsys/bluetooth/audio/csip_crypto.c b/subsys/bluetooth/audio/csip_crypto.c index d51855f02a583ec..d880ca36ce1db58 100644 --- a/subsys/bluetooth/audio/csip_crypto.c +++ b/subsys/bluetooth/audio/csip_crypto.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "common/bt_str.h" @@ -51,16 +52,6 @@ static int aes_cmac(const uint8_t key[BT_CSIP_CRYPTO_KEY_SIZE], return 0; } -static void xor_128(const uint8_t a[16], const uint8_t b[16], uint8_t out[16]) -{ - size_t len = 16; - /* TODO: Identical to the xor_128 from smp.c: Move to util */ - - while (len--) { - *out++ = *a++ ^ *b++; - } -} - int bt_csip_sih(const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE], uint8_t r[BT_CSIP_CRYPTO_PRAND_SIZE], uint8_t out[BT_CSIP_CRYPTO_HASH_SIZE]) { @@ -229,7 +220,7 @@ int bt_csip_sef(const uint8_t k[BT_CSIP_CRYPTO_KEY_SIZE], sys_mem_swap(k1_out, sizeof(k1_out)); } - xor_128(k1_out, sirk, out_sirk); + mem_xor_128(out_sirk, k1_out, sirk); LOG_DBG("out %s", bt_hex(out_sirk, BT_CSIP_SET_SIRK_SIZE)); return 0; diff --git a/subsys/bluetooth/audio/pbp.c b/subsys/bluetooth/audio/pbp.c new file mode 100644 index 000000000000000..9cb589c90950a2c --- /dev/null +++ b/subsys/bluetooth/audio/pbp.c @@ -0,0 +1,81 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(bt_pbp, CONFIG_BT_PBP_LOG_LEVEL); + +int bt_pbp_get_announcement(const uint8_t meta[], size_t meta_len, + enum bt_pbp_announcement_feature features, + struct net_buf_simple *pba_data_buf) +{ + CHECKIF(pba_data_buf == NULL) { + LOG_DBG("No buffer provided for advertising data!\n"); + + return -EINVAL; + } + + CHECKIF((meta == NULL && meta_len != 0) || (meta != NULL && meta_len == 0)) { + LOG_DBG("Invalid metadata combination: %p %zu", meta, meta_len); + + return -EINVAL; + } + + CHECKIF(pba_data_buf->size < (meta_len + BT_PBP_MIN_PBA_SIZE)) { + LOG_DBG("Buffer size needs to be at least %d!\n", meta_len + BT_PBP_MIN_PBA_SIZE); + + return -EINVAL; + } + + /* Fill Announcement data */ + net_buf_simple_add_le16(pba_data_buf, BT_UUID_PBA_VAL); + net_buf_simple_add_u8(pba_data_buf, features); + net_buf_simple_add_u8(pba_data_buf, meta_len); + net_buf_simple_add_mem(pba_data_buf, meta, meta_len); + + return 0; +} + +uint8_t bt_pbp_parse_announcement(struct bt_data *data, + enum bt_pbp_announcement_feature *features, + uint8_t *meta) +{ + uint8_t meta_len = 0; + struct bt_uuid_16 adv_uuid; + + CHECKIF(!data || !features || !meta) { + return -EINVAL; + } + + if (data->data_len < BT_PBP_MIN_PBA_SIZE) { + return -EBADMSG; + } + + if (data->type != BT_DATA_SVC_DATA16) { + return -EINVAL; + } + + if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + return -EINVAL; + } + + if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_PBA)) { + return -EBADMSG; + } + + /* Copy source features, metadata length and metadata from the Announcement */ + *features = data->data[BT_UUID_SIZE_16]; + meta_len = data->data[BT_UUID_SIZE_16 + sizeof(uint8_t)]; + memcpy(meta, data->data + BT_PBP_MIN_PBA_SIZE, meta_len); + + return meta_len; +} diff --git a/subsys/bluetooth/audio/shell/CMakeLists.txt b/subsys/bluetooth/audio/shell/CMakeLists.txt index 18cb1df99338dd2..9913d92994a7212 100644 --- a/subsys/bluetooth/audio/shell/CMakeLists.txt +++ b/subsys/bluetooth/audio/shell/CMakeLists.txt @@ -89,3 +89,7 @@ zephyr_library_sources_ifdef( CONFIG_BT_BAP_BROADCAST_ASSISTANT bap_broadcast_assistant.c ) +zephyr_library_sources_ifdef( + CONFIG_BT_PBP + pbp.c + ) diff --git a/subsys/bluetooth/audio/shell/audio.h b/subsys/bluetooth/audio/shell/audio.h index d204dc3dc2d8a59..a674b474d078b10 100644 --- a/subsys/bluetooth/audio/shell/audio.h +++ b/subsys/bluetooth/audio/shell/audio.h @@ -30,6 +30,7 @@ ssize_t audio_pa_data_add(struct bt_data *data_array, const size_t data_array_si ssize_t csis_ad_data_add(struct bt_data *data, const size_t data_size, const bool discoverable); size_t cap_acceptor_ad_data_add(struct bt_data data[], size_t data_size, bool discoverable); size_t gmap_ad_data_add(struct bt_data data[], size_t data_size); +size_t pbp_ad_data_add(struct bt_data data[], size_t data_size); #if defined(CONFIG_BT_AUDIO) /* Must guard before including audio.h as audio.h uses Kconfigs guarded by diff --git a/subsys/bluetooth/audio/shell/pbp.c b/subsys/bluetooth/audio/shell/pbp.c new file mode 100644 index 000000000000000..9519fd192745d07 --- /dev/null +++ b/subsys/bluetooth/audio/shell/pbp.c @@ -0,0 +1,88 @@ +/** @file + * @brief Bluetooth Public Broadcast Profile shell + */ + +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "shell/bt.h" + +#define PBS_DEMO 'P', 'B', 'P' + +const uint8_t pba_metadata[] = { + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, PBS_DEMO) +}; + +/* Buffer to hold the Public Broadcast Announcement */ +NET_BUF_SIMPLE_DEFINE_STATIC(pbp_ad_buf, BT_PBP_MIN_PBA_SIZE + ARRAY_SIZE(pba_metadata)); + +enum bt_pbp_announcement_feature pbp_features; +extern const struct shell *ctx_shell; + +static int cmd_pbp_set_features(const struct shell *sh, size_t argc, char **argv) +{ + int err = 0; + enum bt_pbp_announcement_feature features; + + features = shell_strtoul(argv[1], 16, &err); + if (err != 0) { + shell_error(sh, "Could not parse received features: %d", err); + + return -ENOEXEC; + } + + pbp_features = features; + + return err; +} + +size_t pbp_ad_data_add(struct bt_data data[], size_t data_size) +{ + int err; + + err = bt_pbp_get_announcement(pba_metadata, + ARRAY_SIZE(pba_metadata), + pbp_features, + &pbp_ad_buf); + + if (err != 0) { + shell_info(ctx_shell, "Create Public Broadcast Announcement"); + } else { + shell_error(ctx_shell, "Failed to create Public Broadcast Announcement: %d", err); + } + + __ASSERT(data_size > 0, "No space for Public Broadcast Announcement"); + data[0].type = BT_DATA_SVC_DATA16; + data[0].data_len = pbp_ad_buf.len; + data[0].data = pbp_ad_buf.data; + + return 1U; +} + +static int cmd_pbp(const struct shell *sh, size_t argc, char **argv) +{ + if (argc > 1) { + shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]); + } else { + shell_error(sh, "%s missing subcomand", argv[0]); + } + + return -ENOEXEC; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(pbp_cmds, + SHELL_CMD_ARG(set_features, NULL, + "Set the Public Broadcast Announcement features", + cmd_pbp_set_features, 2, 0), + SHELL_SUBCMD_SET_END +); + +SHELL_CMD_ARG_REGISTER(pbp, &pbp_cmds, "Bluetooth pbp shell commands", cmd_pbp, 1, 1); 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 20e3fe528e1cde9..f5e566a7bccbe3e 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 @@ -9,6 +9,7 @@ #include #include +#include #include "hal/cpu.h" #include "hal/ccm.h" 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 12e9fd342b979ec..d4611425f2c258a 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 @@ -9,6 +9,7 @@ #include #include +#include #include "hal/cpu.h" #include "hal/ccm.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c index 2ec6a73b4a4b805..467460d2f30b1e7 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c @@ -6,6 +6,7 @@ #include #include +#include #include #include "util/util.h" diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index cb4f09956881c82..2263cd1b23d8516 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -621,6 +621,12 @@ static void rr_st_idle(struct ll_conn *conn, uint8_t evt, void *param) ctx_local->rx_opcode = PDU_DATA_LLCTRL_TYPE_UNUSED; } + /* + * Block/'hold back' future incompatible local procedures + * in case we run a procedure with instant + */ + rr_set_collision(conn, with_instant); + /* Run remote procedure */ rr_act_run(conn); rr_set_state(conn, RR_STATE_ACTIVE); diff --git a/subsys/bluetooth/controller/util/mem.c b/subsys/bluetooth/controller/util/mem.c index 1bd67ee7eb191d3..e0450ac815bce9c 100644 --- a/subsys/bluetooth/controller/util/mem.c +++ b/subsys/bluetooth/controller/util/mem.c @@ -134,24 +134,6 @@ uint8_t mem_nz(uint8_t *src, uint16_t len) return 0; } -/** - * @brief XOR bytes - */ -inline void mem_xor_n(uint8_t *dst, uint8_t *src1, uint8_t *src2, uint16_t len) -{ - while (len--) { - *dst++ = *src1++ ^ *src2++; - } -} - -/** - * @brief XOR 32-bits - */ -void mem_xor_32(uint8_t *dst, uint8_t *src1, uint8_t *src2) -{ - mem_xor_n(dst, src1, src2, 4U); -} - /** * @brief Unit test */ diff --git a/subsys/bluetooth/controller/util/mem.h b/subsys/bluetooth/controller/util/mem.h index 8a8bdb3a62d7aa1..4a345ab253f4c33 100644 --- a/subsys/bluetooth/controller/util/mem.h +++ b/subsys/bluetooth/controller/util/mem.h @@ -63,7 +63,5 @@ uint16_t mem_index_get(const void *mem, const void *mem_pool, uint16_t mem_size) void mem_rcopy(uint8_t *dst, uint8_t const *src, uint16_t len); uint8_t mem_nz(uint8_t *src, uint16_t len); -void mem_xor_n(uint8_t *dst, uint8_t *src1, uint8_t *src2, uint16_t len); -void mem_xor_32(uint8_t *dst, uint8_t *src1, uint8_t *src2); uint32_t mem_ut(void); diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index ba632c1875a9c1c..44a013f14b9e2b8 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -475,20 +475,22 @@ static struct net_buf *l2cap_create_le_sig_pdu(uint8_t code, uint8_t ident, * Any other cleanup in failure to send should be handled by the disconnected * handler. */ -static inline void l2cap_send(struct bt_conn *conn, uint16_t cid, - struct net_buf *buf) +static inline int l2cap_send(struct bt_conn *conn, uint16_t cid, struct net_buf *buf) { - if (bt_l2cap_send(conn, cid, buf)) { + int err = bt_l2cap_send(conn, cid, buf); + + if (err) { net_buf_unref(buf); } + + return err; } #if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL) static void l2cap_chan_send_req(struct bt_l2cap_chan *chan, struct net_buf *buf, k_timeout_t timeout) { - if (bt_l2cap_send(chan->conn, BT_L2CAP_CID_LE_SIG, buf)) { - net_buf_unref(buf); + if (l2cap_send(chan->conn, BT_L2CAP_CID_LE_SIG, buf)) { return; } @@ -971,9 +973,11 @@ static void l2cap_chan_tx_give_credits(struct bt_l2cap_le_chan *chan, atomic_add(&chan->tx.credits, credits); - if (!atomic_test_and_set_bit(chan->chan.status, BT_L2CAP_STATUS_OUT) && - chan->chan.ops->status) { - chan->chan.ops->status(&chan->chan, chan->chan.status); + if (!atomic_test_and_set_bit(chan->chan.status, BT_L2CAP_STATUS_OUT)) { + LOG_DBG("chan %p unpaused", chan); + if (chan->chan.ops->status) { + chan->chan.ops->status(&chan->chan, chan->chan.status); + } } } @@ -1204,8 +1208,7 @@ static void le_conn_req(struct bt_l2cap *l2cap, uint8_t ident, rsp: rsp->result = sys_cpu_to_le16(result); - if (bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf)) { - net_buf_unref(buf); + if (l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf)) { return; } @@ -1324,8 +1327,7 @@ static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident, net_buf_add_mem(buf, dcid, sizeof(scid) * req_cid_count); - if (bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf)) { - net_buf_unref(buf); + if (l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf)) { goto callback; } @@ -2045,11 +2047,11 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, return err; } - /* Check if there is no credits left clear output status and notify its - * change. - */ + /* Notify channel user that it can't send anymore on this channel. */ if (!atomic_get(&ch->tx.credits)) { + LOG_DBG("chan %p paused", ch); atomic_clear_bit(ch->chan.status, BT_L2CAP_STATUS_OUT); + if (ch->chan.ops->status) { ch->chan.ops->status(&ch->chan, ch->chan.status); } @@ -2344,7 +2346,6 @@ static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan, #if defined(CONFIG_BT_L2CAP_SEG_RECV) static int l2cap_chan_send_credits_pdu(struct bt_conn *conn, uint16_t cid, uint16_t credits) { - int err; struct net_buf *buf; struct bt_l2cap_le_credits *ev; @@ -2359,13 +2360,7 @@ static int l2cap_chan_send_credits_pdu(struct bt_conn *conn, uint16_t cid, uint1 .credits = sys_cpu_to_le16(credits), }; - err = bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf); - if (err) { - net_buf_unref(buf); - return err; - } - - return 0; + return l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf); } /** @@ -2782,7 +2777,6 @@ int bt_l2cap_update_conn_param(struct bt_conn *conn, { struct bt_l2cap_conn_param_req *req; struct net_buf *buf; - int err; buf = l2cap_create_le_sig_pdu(BT_L2CAP_CONN_PARAM_REQ, get_ident(), sizeof(*req)); @@ -2796,13 +2790,7 @@ int bt_l2cap_update_conn_param(struct bt_conn *conn, req->latency = sys_cpu_to_le16(param->latency); req->timeout = sys_cpu_to_le16(param->timeout); - err = bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf); - if (err) { - net_buf_unref(buf); - return err; - } - - return 0; + return l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf); } static void l2cap_connected(struct bt_l2cap_chan *chan) diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 2c110dc43a3885b..95809d237686055 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -1829,15 +1829,6 @@ static uint8_t smp_send_pairing_random(struct bt_smp *smp) } #if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) -static void xor_128(const uint8_t p[16], const uint8_t q[16], uint8_t r[16]) -{ - size_t len = 16; - - while (len--) { - *r++ = *p++ ^ *q++; - } -} - static int smp_c1(const uint8_t k[16], const uint8_t r[16], const uint8_t preq[7], const uint8_t pres[7], const bt_addr_le_t *ia, const bt_addr_le_t *ra, @@ -1864,7 +1855,7 @@ static int smp_c1(const uint8_t k[16], const uint8_t r[16], /* c1 = e(k, e(k, r XOR p1) XOR p2) */ /* Using enc_data as temporary output buffer */ - xor_128(r, p1, enc_data); + mem_xor_128(enc_data, r, p1); err = bt_encrypt_le(k, enc_data, enc_data); if (err) { @@ -1878,7 +1869,7 @@ static int smp_c1(const uint8_t k[16], const uint8_t r[16], LOG_DBG("p2 %s", bt_hex(p2, 16)); - xor_128(enc_data, p2, enc_data); + mem_xor_128(enc_data, p2, enc_data); return bt_encrypt_le(k, enc_data, enc_data); } diff --git a/subsys/bluetooth/mesh/main.c b/subsys/bluetooth/mesh/main.c index 2689a3355c1f977..1b80233cec17e56 100644 --- a/subsys/bluetooth/mesh/main.c +++ b/subsys/bluetooth/mesh/main.c @@ -462,6 +462,22 @@ int bt_mesh_suspend(void) bt_mesh_access_suspend(); + if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { + err = bt_mesh_pb_gatt_srv_disable(); + if (err && err != -EALREADY) { + LOG_WRN("Disabling PB-GATT failed (err %d)", err); + return err; + } + } + + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + err = bt_mesh_proxy_gatt_disable(); + if (err && err != -EALREADY) { + LOG_WRN("Disabling GATT proxy failed (err %d)", err); + return err; + } + } + err = bt_mesh_adv_disable(); if (err) { atomic_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED); @@ -508,6 +524,22 @@ int bt_mesh_resume(void) return err; } + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && bt_mesh_is_provisioned()) { + err = bt_mesh_proxy_gatt_enable(); + if (err) { + LOG_WRN("Re-enabling GATT proxy failed (err %d)", err); + return err; + } + } + + if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && !bt_mesh_is_provisioned()) { + err = bt_mesh_pb_gatt_srv_enable(); + if (err) { + LOG_WRN("Re-enabling PB-GATT failed (err %d)", err); + return err; + } + } + err = bt_mesh_scan_enable(); if (err) { LOG_WRN("Re-enabling scanning failed (err %d)", err); @@ -524,7 +556,13 @@ int bt_mesh_resume(void) bt_mesh_model_foreach(model_resume, NULL); - return err; + err = bt_mesh_adv_gatt_send(); + if (err && (err != -ENOTSUP)) { + LOG_WRN("GATT send failed (err %d)", err); + return err; + } + + return 0; } int bt_mesh_init(const struct bt_mesh_prov *prov, diff --git a/subsys/bluetooth/mesh/proxy_srv.c b/subsys/bluetooth/mesh/proxy_srv.c index 25a44abfdedc6ab..a903d94ffa990b6 100644 --- a/subsys/bluetooth/mesh/proxy_srv.c +++ b/subsys/bluetooth/mesh/proxy_srv.c @@ -975,6 +975,8 @@ static void svc_reg_work_handler(struct k_work *work) int bt_mesh_proxy_gatt_enable(void) { + int err; + LOG_DBG(""); if (!bt_mesh_is_provisioned()) { @@ -986,7 +988,13 @@ int bt_mesh_proxy_gatt_enable(void) } svc_reg_attempts = PROXY_SVC_REG_ATTEMPTS; - return k_work_schedule(&svc_reg_work, PROXY_SVC_INIT_TIMEOUT); + err = k_work_schedule(&svc_reg_work, PROXY_SVC_INIT_TIMEOUT); + if (err < 0) { + LOG_ERR("Enabling GATT proxy failed (err %d)", err); + return err; + } + + return 0; } void bt_mesh_proxy_gatt_disconnect(void) diff --git a/subsys/bluetooth/services/hrs.c b/subsys/bluetooth/services/hrs.c index 013591516a1de94..875129ac185f87d 100644 --- a/subsys/bluetooth/services/hrs.c +++ b/subsys/bluetooth/services/hrs.c @@ -14,12 +14,14 @@ #include #include #include +#include #include #include #include #include #include +#include #define LOG_LEVEL CONFIG_BT_HRS_LOG_LEVEL #include @@ -51,14 +53,23 @@ LOG_MODULE_REGISTER(hrs); (BT_GATT_PERM_READ | BT_GATT_PERM_WRITE)) \ static uint8_t hrs_blsc; +static sys_slist_t hrs_cbs = SYS_SLIST_STATIC_INIT(&hrs_cbs); static void hrmc_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) { ARG_UNUSED(attr); + struct bt_hrs_cb *listener; + bool notif_enabled = (value == BT_GATT_CCC_NOTIFY); LOG_INF("HRS notifications %s", notif_enabled ? "enabled" : "disabled"); + + SYS_SLIST_FOR_EACH_CONTAINER(&hrs_cbs, listener, _node) { + if (listener->ntf_changed) { + listener->ntf_changed(notif_enabled); + } + } } static ssize_t read_blsc(struct bt_conn *conn, const struct bt_gatt_attr *attr, @@ -91,6 +102,30 @@ static int hrs_init(void) return 0; } +int bt_hrs_cb_register(struct bt_hrs_cb *cb) +{ + CHECKIF(cb == NULL) { + return -EINVAL; + } + + sys_slist_append(&hrs_cbs, &cb->_node); + + return 0; +} + +int bt_hrs_cb_unregister(struct bt_hrs_cb *cb) +{ + CHECKIF(cb == NULL) { + return -EINVAL; + } + + if (!sys_slist_find_and_remove(&hrs_cbs, &cb->_node)) { + return -ENOENT; + } + + return 0; +} + int bt_hrs_notify(uint16_t heartrate) { int rc; diff --git a/subsys/fs/fuse_fs_access.c b/subsys/fs/fuse_fs_access.c index e39416f91cf78d8..d3df397842f9aa5 100644 --- a/subsys/fs/fuse_fs_access.c +++ b/subsys/fs/fuse_fs_access.c @@ -65,8 +65,15 @@ static void release_file_handle(size_t handle) static bool is_mount_point(const char *path) { char dir_path[PATH_MAX]; + size_t len; - sprintf(dir_path, "%s", path); + len = strlen(path); + if (len >= sizeof(dir_path)) { + return false; + } + + memcpy(dir_path, path, len); + dir_path[len] = '\0'; return strcmp(dirname(dir_path), "/") == 0; } diff --git a/subsys/logging/Kconfig.formatting b/subsys/logging/Kconfig.formatting index 271ca066d2ce8e1..44b9244e2969523 100644 --- a/subsys/logging/Kconfig.formatting +++ b/subsys/logging/Kconfig.formatting @@ -38,6 +38,11 @@ config LOG_MIPI_SYST_USE_CATALOG help Use MIPI Sys-T Catalog for logging instead of plain text. +config LOG_MIPI_SYST_DISABLE_TIMESTAMP + bool "Disable MIPI Sys-T protocol timestamp" + help + Remove the timestamp from the MIPI Sys-T protocol. + config LOG_MIPI_SYST_CATALOG_ARGS_BUFFER_SIZE int "Size of temporary arguments buffer when using Sys-T Catalog" depends on LOG_MIPI_SYST_USE_CATALOG diff --git a/subsys/logging/backends/Kconfig.native_posix b/subsys/logging/backends/Kconfig.native_posix index bde09c9f244d6dd..4c7348819744863 100644 --- a/subsys/logging/backends/Kconfig.native_posix +++ b/subsys/logging/backends/Kconfig.native_posix @@ -4,7 +4,7 @@ config LOG_BACKEND_NATIVE_POSIX bool "Native backend" depends on ARCH_POSIX - default y if !SERIAL + default y select LOG_OUTPUT help Enable backend in native_posix diff --git a/subsys/logging/mipi_syst/platform.h b/subsys/logging/mipi_syst/platform.h index 3c4568175235ecb..27b19fa113f828f 100644 --- a/subsys/logging/mipi_syst/platform.h +++ b/subsys/logging/mipi_syst/platform.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Intel Corporation + * Copyright (c) 2019 - 2023 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,10 @@ extern "C" { #endif +#if defined(CONFIG_LOG_MIPI_SYST_DISABLE_TIMESTAMP) +#undef MIPI_SYST_PCFG_ENABLE_TIMESTAMP +#endif + #define MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE CONFIG_LOG_MIPI_SYST_ARGS_BUFFER_SIZE #if defined(CONFIG_MIPI_SYST_STP) diff --git a/subsys/modem/modem_cmux.c b/subsys/modem/modem_cmux.c index 7f40fa6e95d1217..258f969c4982af2 100644 --- a/subsys/modem/modem_cmux.c +++ b/subsys/modem/modem_cmux.c @@ -546,6 +546,7 @@ 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; + uint32_t written; if (dlci->state != MODEM_CMUX_DLCI_STATE_OPEN) { LOG_DBG("Unexpected UIH frame"); @@ -553,8 +554,11 @@ static void modem_cmux_on_dlci_frame_uih(struct modem_cmux_dlci *dlci) } k_mutex_lock(&dlci->receive_rb_lock, K_FOREVER); - ring_buf_put(&dlci->receive_rb, cmux->frame.data, cmux->frame.data_len); + written = ring_buf_put(&dlci->receive_rb, cmux->frame.data, cmux->frame.data_len); k_mutex_unlock(&dlci->receive_rb_lock); + if (written != cmux->frame.data_len) { + LOG_WRN("DLCI %u receive buffer overrun", dlci->dlci_address); + } modem_pipe_notify_receive_ready(&dlci->pipe); } diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 23fec86262a8a27..41df924607c8037 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -28,6 +28,8 @@ LOG_MODULE_REGISTER(net_tcp, CONFIG_NET_TCP_LOG_LEVEL); #define ACK_TIMEOUT_MS CONFIG_NET_TCP_ACK_TIMEOUT #define ACK_TIMEOUT K_MSEC(ACK_TIMEOUT_MS) +#define LAST_ACK_TIMEOUT_MS tcp_fin_timeout_ms +#define LAST_ACK_TIMEOUT K_MSEC(LAST_ACK_TIMEOUT_MS) #define FIN_TIMEOUT K_MSEC(tcp_fin_timeout_ms) #define ACK_DELAY K_MSEC(100) #define ZWP_MAX_DELAY_MS 120000 @@ -712,6 +714,12 @@ static void tcp_conn_release(struct k_work *work) struct tcp *conn = CONTAINER_OF(work, struct tcp, conn_release); struct net_pkt *pkt; +#if defined(CONFIG_NET_TEST) + if (conn->test_closed_cb != NULL) { + conn->test_closed_cb(conn, conn->test_user_data); + } +#endif + k_mutex_lock(&tcp_lock, K_FOREVER); /* Application is no longer there, unref any remaining packets on the @@ -760,6 +768,18 @@ static void tcp_conn_release(struct k_work *work) k_mutex_unlock(&tcp_lock); } +#if defined(CONFIG_NET_TEST) +void tcp_install_close_cb(struct net_context *ctx, + net_tcp_closed_cb_t cb, + void *user_data) +{ + NET_ASSERT(ctx->tcp != NULL); + + ((struct tcp *)ctx->tcp)->test_closed_cb = cb; + ((struct tcp *)ctx->tcp)->test_user_data = user_data; +} +#endif + static int tcp_conn_unref(struct tcp *conn) { int ref_count = atomic_get(&conn->ref_count); @@ -1774,9 +1794,9 @@ static void tcp_resend_data(struct k_work *work) conn->send_data_retries++; if (ret == 0) { if (conn->in_close && conn->send_data_total == 0) { - NET_DBG("TCP connection in active close, " + NET_DBG("TCP connection in %s close, " "not disposing yet (waiting %dms)", - tcp_fin_timeout_ms); + "active", tcp_fin_timeout_ms); k_work_reschedule_for_queue(&tcp_work_q, &conn->fin_timer, FIN_TIMEOUT); @@ -1857,6 +1877,40 @@ static void tcp_fin_timeout(struct k_work *work) (void)tcp_conn_close(conn, -ETIMEDOUT); } +static void tcp_last_ack_timeout(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct tcp *conn = CONTAINER_OF(dwork, struct tcp, fin_timer); + + NET_DBG("Did not receive %s in %dms", "last ACK", LAST_ACK_TIMEOUT_MS); + NET_DBG("conn: %p %s", conn, tcp_conn_state(conn, NULL)); + + (void)tcp_conn_close(conn, -ETIMEDOUT); +} + +static void tcp_setup_last_ack_timer(struct tcp *conn) +{ + /* Just in case the last ack is lost, install a timer that will + * close the connection in that case. Use the fin_timer for that + * as the fin handling cannot be done in this passive close state. + * Instead of default tcp_fin_timeout() function, have a separate + * function to catch this last ack case. + */ + k_work_init_delayable(&conn->fin_timer, tcp_last_ack_timeout); + + NET_DBG("TCP connection in %s close, " + "not disposing yet (waiting %dms)", + "passive", LAST_ACK_TIMEOUT_MS); + k_work_reschedule_for_queue(&tcp_work_q, + &conn->fin_timer, + LAST_ACK_TIMEOUT); +} + +static void tcp_cancel_last_ack_timer(struct tcp *conn) +{ + k_work_cancel_delayable(&conn->fin_timer); +} + #if defined(CONFIG_NET_TCP_KEEPALIVE) static void tcp_send_keepalive_probe(struct k_work *work) { @@ -2922,6 +2976,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) next = TCP_LAST_ACK; verdict = NET_OK; keep_alive_timer_stop(conn); + tcp_setup_last_ack_timer(conn); break; } else if (th && FL(&fl, ==, FIN, th_seq(th) == conn->ack)) { conn_ack(conn, + 1); @@ -2946,6 +3001,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) tcp_out(conn, FIN | ACK); next = TCP_LAST_ACK; keep_alive_timer_stop(conn); + tcp_setup_last_ack_timer(conn); break; } @@ -3052,6 +3108,10 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) tcp_send_timer_cancel(conn); 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); verdict = NET_OK; @@ -3126,6 +3186,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) case TCP_CLOSE_WAIT: tcp_out(conn, FIN); next = TCP_LAST_ACK; + tcp_setup_last_ack_timer(conn); break; case TCP_LAST_ACK: if (th && FL(&fl, ==, ACK, th_seq(th) == conn->ack)) { @@ -3133,6 +3194,9 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) do_close = true; verdict = NET_OK; close_status = 0; + + /* Remove the last ack timer if we received it in time */ + tcp_cancel_last_ack_timer(conn); } break; case TCP_CLOSED: @@ -3456,8 +3520,9 @@ int net_tcp_put(struct net_context *context) } else { int ret; - NET_DBG("TCP connection in active close, not " - "disposing yet (waiting %dms)", tcp_fin_timeout_ms); + NET_DBG("TCP connection in %s close, " + "not disposing yet (waiting %dms)", + "active", tcp_fin_timeout_ms); k_work_reschedule_for_queue(&tcp_work_q, &conn->fin_timer, FIN_TIMEOUT); diff --git a/subsys/net/ip/tcp_private.h b/subsys/net/ip/tcp_private.h index 5d5d78d916b258f..1f2eee24989b47f 100644 --- a/subsys/net/ip/tcp_private.h +++ b/subsys/net/ip/tcp_private.h @@ -250,6 +250,9 @@ struct tcp_collision_avoidance_reno { }; #endif +struct tcp; +typedef void (*net_tcp_closed_cb_t)(struct tcp *conn, void *user_data); + struct tcp { /* TCP connection */ sys_snode_t next; struct net_context *context; @@ -263,6 +266,10 @@ struct tcp { /* TCP connection */ struct tcp *accepted_conn; }; net_context_connect_cb_t connect_cb; +#if defined(CONFIG_NET_TEST) + net_tcp_closed_cb_t test_closed_cb; + void *test_user_data; +#endif struct k_mutex lock; struct k_sem connect_sem; /* semaphore for blocking connect */ struct k_sem tx_sem; /* Semaphore indicating if transfers are blocked . */ @@ -345,3 +352,9 @@ struct tcp { /* TCP connection */ _flags(_fl, _op, _mask, sizeof(#_args) > 1 ? _args : true) typedef void (*net_tcp_cb_t)(struct tcp *conn, void *user_data); + +#if defined(CONFIG_NET_TEST) +void tcp_install_close_cb(struct net_context *ctx, + net_tcp_closed_cb_t cb, + void *user_data); +#endif diff --git a/subsys/net/ip/utils.c b/subsys/net/ip/utils.c index a1b3facd9056d7a..a52c96a16b634e9 100644 --- a/subsys/net/ip/utils.c +++ b/subsys/net/ip/utils.c @@ -539,7 +539,7 @@ uint16_t calc_chksum(uint16_t sum_in, const uint8_t *data, size_t len) * and the offset of starting */ if (odd_start == CHECKSUM_BIG_ENDIAN) { - sum = __bswap_16(sum_in); + sum = BSWAP_16(sum_in); } else { sum = sum_in; } @@ -591,7 +591,7 @@ uint16_t calc_chksum(uint16_t sum_in, const uint8_t *data, size_t len) * and the offset of starting */ if (odd_start == CHECKSUM_BIG_ENDIAN) { - return __bswap_16((uint16_t)sum); + return BSWAP_16((uint16_t)sum); } else { return sum; } diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 3aa674e73b70f5a..c78996351052149 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -15,6 +15,7 @@ LOG_MODULE_REGISTER(net_wifi_shell, LOG_LEVEL_INF); #include #include #include +#include #include #include #include @@ -782,9 +783,9 @@ static int cmd_wifi_ps(const struct shell *sh, size_t argc, char *argv[]) return 0; } - if (!strncmp(argv[1], "on", 2)) { + if (!strncasecmp(argv[1], "on", 2)) { params.enabled = WIFI_PS_ENABLED; - } else if (!strncmp(argv[1], "off", 3)) { + } else if (!strncasecmp(argv[1], "off", 3)) { params.enabled = WIFI_PS_DISABLED; } else { shell_fprintf(sh, SHELL_WARNING, "Invalid argument\n"); @@ -813,9 +814,9 @@ static int cmd_wifi_ps_mode(const struct shell *sh, size_t argc, char *argv[]) context.sh = sh; - if (!strncmp(argv[1], "legacy", 6)) { + if (!strncasecmp(argv[1], "legacy", 6)) { params.mode = WIFI_PS_MODE_LEGACY; - } else if (!strncmp(argv[1], "wmm", 3)) { + } else if (!strncasecmp(argv[1], "WMM", 4)) { params.mode = WIFI_PS_MODE_WMM; } else { shell_fprintf(sh, SHELL_WARNING, "Invalid PS mode\n"); @@ -1243,9 +1244,9 @@ static int cmd_wifi_ps_wakeup_mode(const struct shell *sh, size_t argc, char *ar context.sh = sh; - if (!strncmp(argv[1], "dtim", 4)) { + if (!strncasecmp(argv[1], "dtim", 4)) { params.wakeup_mode = WIFI_PS_WAKEUP_MODE_DTIM; - } else if (!strncmp(argv[1], "listen_interval", 15)) { + } else if (!strncasecmp(argv[1], "listen_interval", 15)) { params.wakeup_mode = WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL; } else { shell_fprintf(sh, SHELL_WARNING, "Invalid argument\n"); @@ -1601,7 +1602,7 @@ static int cmd_wifi_packet_filter(const struct shell *sh, size_t argc, char *arg SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap, SHELL_CMD_ARG(disable, NULL, - "Disable Access Point mode", + "Disable Access Point mode.\n", cmd_wifi_ap_disable, 1, 0), SHELL_CMD_ARG(enable, NULL, @@ -1611,7 +1612,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap, "[Security type: valid only for secure SSIDs]\n" "0:None, 1:WPA2-PSK, 2:WPA2-PSK-256, 3:SAE, 4:WAPI, 5:EAP, 6:WEP, 7: WPA-PSK\n" "[MFP (optional: needs security type to be specified)]\n" - ": 0:Disable, 1:Optional, 2:Required", + ": 0:Disable, 1:Optional, 2:Required.\n", cmd_wifi_ap_enable, 2, 4), SHELL_SUBCMD_SET_END @@ -1619,30 +1620,30 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap, SHELL_STATIC_SUBCMD_SET_CREATE(wifi_twt_ops, SHELL_CMD_ARG(quick_setup, NULL, " Start a TWT flow with defaults:\n" - " \n", + " .\n", cmd_wifi_twt_setup_quick, 3, 0), SHELL_CMD_ARG(setup, NULL, " Start a TWT flow:\n" "\n" "\n" " " - " \n", + " .\n", cmd_wifi_twt_setup, 11, 0), SHELL_CMD_ARG(teardown, NULL, " Teardown a TWT flow:\n" "\n" "\n" - " \n", + " .\n", cmd_wifi_twt_teardown, 5, 0), - SHELL_CMD_ARG(teardown_all, NULL, " Teardown all TWT flows\n", + SHELL_CMD_ARG(teardown_all, NULL, " Teardown all TWT flows.\n", cmd_wifi_twt_teardown_all, 1, 0), SHELL_SUBCMD_SET_END ); SHELL_STATIC_SUBCMD_SET_CREATE(wifi_commands, - SHELL_CMD(ap, &wifi_cmd_ap, "Access Point mode commands", NULL), + SHELL_CMD(ap, &wifi_cmd_ap, "Access Point mode commands.\n", NULL), SHELL_CMD_ARG(connect, NULL, "Connect to a Wi-Fi AP\n" "\"\"\n" @@ -1651,111 +1652,108 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_commands, "[Security type: valid only for secure SSIDs]\n" "0:None, 1:WPA2-PSK, 2:WPA2-PSK-256, 3:SAE, 4:WAPI, 5:EAP, 6:WEP, 7: WPA-PSK\n" "[MFP (optional: needs security type to be specified)]\n" - ": 0:Disable, 1:Optional, 2:Required", + ": 0:Disable, 1:Optional, 2:Required.\n", cmd_wifi_connect, - 2, 5), - SHELL_CMD_ARG(disconnect, NULL, "Disconnect from the Wi-Fi AP", + 2, 4), + SHELL_CMD_ARG(disconnect, NULL, "Disconnect from the Wi-Fi AP.\n", cmd_wifi_disconnect, 1, 0), - SHELL_CMD_ARG(ps, NULL, "Configure Wi-F PS on/off, no arguments will dump config", + SHELL_CMD_ARG(ps, NULL, "Configure or display Wi-Fi power save state.\n" + "[on/off]\n", cmd_wifi_ps, 1, 1), SHELL_CMD_ARG(ps_mode, NULL, - "\n", + ".\n", cmd_wifi_ps_mode, 2, 0), SHELL_CMD_ARG(scan, NULL, "Scan for Wi-Fi APs\n" - "OPTIONAL PARAMETERS:\n" - "[-t, --type ] : Preferred mode of scan. The actual mode of scan can depend on factors such as the Wi-Fi chip implementation, regulatory domain restrictions. Default type is active.\n" - "[-b, --bands ] : Bands to be scanned where 2: 2.4 GHz, 5: 5 GHz, 6: 6 GHz.\n" - "[-a, --dwell_time_active ] : Active scan dwell time (in ms) on a channel. Range 5 ms to 1000 ms.\n" - "[-p, --dwell_time_passive ] : Passive scan dwell time (in ms) on a channel. Range 10 ms to 1000 ms.\n" - "[-s, --ssid : SSID to scan for. Can be provided multiple times.\n" - "[-m, --max_bss ] : Maximum BSSes to scan for. Range 1 - 65535.\n" + "[-t, --type ] : Preferred mode of scan. The actual mode of scan can depend on factors such as the Wi-Fi chip implementation, regulatory domain restrictions. Default type is active\n" + "[-b, --bands ] : Bands to be scanned where 2: 2.4 GHz, 5: 5 GHz, 6: 6 GHz\n" + "[-a, --dwell_time_active ] : Active scan dwell time (in ms) on a channel. Range 5 ms to 1000 ms\n" + "[-p, --dwell_time_passive ] : Passive scan dwell time (in ms) on a channel. Range 10 ms to 1000 ms\n" + "[-s, --ssid : SSID to scan for. Can be provided multiple times\n" + "[-m, --max_bss ] : Maximum BSSes to scan for. Range 1 - 65535\n" "[-c, --chans ] : Channels to be scanned. The channels must be specified in the form band1:chan1,chan2_band2:chan3,..etc. band1, band2 must be valid band values and chan1, chan2, chan3 must be specified as a list of comma separated values where each value is either a single channel or a channel range specified as chan_start-chan_end. Each band channel set has to be separated by a _. For example, a valid channel specification can be 2:1,6-11,14_5:36,149-165,44\n" - "[-h, --help] : Print out the help for the scan command.", + "[-h, --help] : Print out the help for the scan command.\n", cmd_wifi_scan, 1, 8), - SHELL_CMD_ARG(statistics, NULL, "Wi-Fi interface statistics", cmd_wifi_stats, 1, 0), - SHELL_CMD_ARG(status, NULL, "Status of the Wi-Fi interface", cmd_wifi_status, 1, 0), - SHELL_CMD(twt, &wifi_twt_ops, "Manage TWT flows", NULL), + SHELL_CMD_ARG(statistics, NULL, "Wi-Fi interface statistics.\n", cmd_wifi_stats, 1, 0), + SHELL_CMD_ARG(status, NULL, "Status of the Wi-Fi interface.\n", cmd_wifi_status, 1, 0), + SHELL_CMD(twt, &wifi_twt_ops, "Manage TWT flows.\n", NULL), SHELL_CMD_ARG(reg_domain, NULL, "Set or Get Wi-Fi regulatory domain\n" - "Usage: wifi reg_domain [ISO/IEC 3166-1 alpha2] [-f]\n" + "[ISO/IEC 3166-1 alpha2]: Regulatory domain\n" "[-f]: Force to use this regulatory hint over any other regulatory hints\n" - "Note: This may cause regulatory compliance issues, use it at your own risk.", + "Note: This may cause regulatory compliance issues, use it at your own risk.\n", cmd_wifi_reg_domain, - 1, 1), + 1, 2), SHELL_CMD_ARG(mode, NULL, "mode operational setting\n" "This command may be used to set the Wi-Fi device into a specific mode of operation\n" - "parameters:" - "[-i, --if-index ] : Interface index.\n" - "[-s, --sta] : Station mode.\n" - "[-m, --monitor] : Monitor mode.\n" - "[-p, --promiscuous] : Promiscuous mode.\n" - "[-t, --tx-injection] : TX-Injection mode.\n" - "[-a, --ap] : AP mode.\n" - "[-k, --softap] : Softap mode.\n" - "[-h, --help] : Help.\n" - "[-g, --get] : Get current mode for a specific interface index.\n" + "[-i, --if-index ] : Interface index\n" + "[-s, --sta] : Station mode\n" + "[-m, --monitor] : Monitor mode\n" + "[-p, --promiscuous] : Promiscuous mode\n" + "[-t, --tx-injection] : TX-Injection mode\n" + "[-a, --ap] : AP mode\n" + "[-k, --softap] : Softap mode\n" + "[-h, --help] : Help\n" + "[-g, --get] : Get current mode for a specific interface index\n" "Usage: Get operation example for interface index 1\n" "wifi mode -g -i1\n" "Set operation example for interface index 1 - set station+promiscuous\n" - "wifi mode -i1 -sp\n", + "wifi mode -i1 -sp.\n", cmd_wifi_mode, 1, 9), SHELL_CMD_ARG(packet_filter, NULL, "mode filter setting\n" "This command is used to set packet filter setting when\n" - "monitor, TX-Injection and promiscuous mode is enabled.\n" + "monitor, TX-Injection and promiscuous mode is enabled\n" "The different packet filter modes are control, management, data and enable all filters\n" - "parameters:" - "[-i, --if-index ] : Interface index.\n" + "[-i, --if-index ] : Interface index\n" "[-a, --all] : Enable all packet filter modes\n" - "[-m, --mgmt] : Enable management packets to allowed up the stack.\n" - "[-c, --ctrl] : Enable control packets to be allowed up the stack.\n" - "[-d, --data] : Enable Data packets to be allowed up the stack.\n" - "[-g, --get] : Get current filter settings for a specific interface index.\n" + "[-m, --mgmt] : Enable management packets to allowed up the stack\n" + "[-c, --ctrl] : Enable control packets to be allowed up the stack\n" + "[-d, --data] : Enable Data packets to be allowed up the stack\n" + "[-g, --get] : Get current filter settings for a specific interface index\n" "[-b, --capture-len ] : Capture length buffer size for each packet to be captured\n" - "[-h, --help] : Help.\n" + "[-h, --help] : Help\n" "Usage: Get operation example for interface index 1\n" "wifi packet_filter -g -i1\n" "Set operation example for interface index 1 - set data+management frame filter\n" - "wifi packet_filter -i1 -md\n", + "wifi packet_filter -i1 -md.\n", cmd_wifi_packet_filter, 1, 8), SHELL_CMD_ARG(channel, NULL, "wifi channel setting\n" "This command is used to set the channel when\n" - "monitor or TX-Injection mode is enabled.\n" + "monitor or TX-Injection mode is enabled\n" "Currently 20 MHz is only supported and no BW parameter is provided\n" - "parameters:" - "[-i, --if-index ] : Interface index.\n" - "[-c, --channel ] : Set a specific channel number to the lower layer.\n" - "[-g, --get] : Get current set channel number from the lower layer.\n" - "[-h, --help] : Help.\n" + "[-i, --if-index ] : Interface index\n" + "[-c, --channel ] : Set a specific channel number to the lower layer\n" + "[-g, --get] : Get current set channel number from the lower layer\n" + "[-h, --help] : Help\n" "Usage: Get operation example for interface index 1\n" "wifi channel -g -i1\n" "Set operation example for interface index 1 (setting channel 5)\n" - "wifi -i1 -c5\n", + "wifi -i1 -c5.\n", cmd_wifi_channel, 1, 4), SHELL_CMD_ARG(ps_timeout, NULL, - " - PS inactivity timer(in ms)", + " - PS inactivity timer(in ms).\n", cmd_wifi_ps_timeout, 2, 0), SHELL_CMD_ARG(ps_listen_interval, NULL, - " - Listen interval in the range of <0-65535>", + " - Listen interval in the range of <0-65535>.\n", cmd_wifi_listen_interval, 2, 0), SHELL_CMD_ARG(ps_wakeup_mode, NULL, - "\n", + ".\n", cmd_wifi_ps_wakeup_mode, 2, 0), diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.c b/subsys/net/lib/lwm2m/lwm2m_engine.c index 639f65ea0fa4e6e..e08bb4ca17ea6f0 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.c +++ b/subsys/net/lib/lwm2m/lwm2m_engine.c @@ -1259,6 +1259,12 @@ int lwm2m_engine_pause(void) suspend_engine_thread = true; lwm2m_engine_wake_up(); + /* Check if pause requested within a engine thread, a callback for example. */ + if (engine_thread_id == k_current_get()) { + LOG_DBG("Pause requested"); + return 0; + } + while (active_engine_thread) { k_msleep(10); } @@ -1275,10 +1281,7 @@ int lwm2m_engine_resume(void) k_thread_resume(engine_thread_id); lwm2m_engine_wake_up(); - while (!active_engine_thread) { - k_msleep(10); - } - LOG_INF("LWM2M engine thread resume"); + return 0; } diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index 677879304f850cb..480c64372e8441d 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -46,6 +46,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include "lwm2m_object.h" #include "lwm2m_obj_access_control.h" #include "lwm2m_obj_server.h" +#include "lwm2m_obj_gateway.h" #include "lwm2m_rw_link_format.h" #include "lwm2m_rw_oma_tlv.h" #include "lwm2m_rw_plain_text.h" @@ -479,7 +480,7 @@ void lwm2m_engine_context_init(struct lwm2m_ctx *client_ctx) } /* utility functions */ -static int coap_options_to_path(struct coap_option *opt, int options_count, +int coap_options_to_path(struct coap_option *opt, int options_count, struct lwm2m_obj_path *path) { uint16_t len, @@ -2268,6 +2269,15 @@ static int handle_request(struct coap_packet *request, struct lwm2m_message *msg msg->token = token; } + if (IS_ENABLED(CONFIG_LWM2M_GATEWAY_OBJ_SUPPORT)) { + r = lwm2m_gw_handle_req(msg); + if (r == 0) { + return 0; + } else if (r != -ENOENT) { + goto error; + } + } + /* parse the URL path into components */ r = coap_find_options(msg->in.in_cpkt, COAP_OPTION_URI_PATH, options, ARRAY_SIZE(options)); if (r < 0) { diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.h b/subsys/net/lib/lwm2m/lwm2m_message_handling.h index c41fbbac0eeef08..3ac014b5db8bf4c 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.h +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.h @@ -39,6 +39,8 @@ #define NUM_OUTPUT_BLOCK_CONTEXT CONFIG_LWM2M_NUM_OUTPUT_BLOCK_CONTEXT #endif +int coap_options_to_path(struct coap_option *opt, int options_count, + struct lwm2m_obj_path *path); /* LwM2M message functions */ struct lwm2m_message *lwm2m_get_message(struct lwm2m_ctx *client_ctx); struct lwm2m_message *find_msg(struct coap_pending *pending, struct coap_reply *reply); diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c b/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c index 711fd5fe127d304..5bb12f80f478321 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_gateway.c @@ -59,6 +59,7 @@ static struct lwm2m_engine_obj_field fields[] = { static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][GATEWAY_MAX_ID]; static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; +lwm2m_engine_gateway_msg_cb gateway_msg_cb[MAX_INSTANCE_COUNT]; static int prefix_validation_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, @@ -146,6 +147,57 @@ static struct lwm2m_engine_obj_inst *lwm2m_gw_create(uint16_t obj_inst_id) return &inst[index]; } +int lwm2m_gw_handle_req(struct lwm2m_message *msg) +{ + struct coap_option options[4]; + int ret; + + ret = coap_find_options(msg->in.in_cpkt, COAP_OPTION_URI_PATH, options, + ARRAY_SIZE(options)); + if (ret < 0) { + return ret; + } + + for (int index = 0; index < MAX_INSTANCE_COUNT; index++) { + /* Skip uninitialized objects */ + if (!inst[index].obj) { + continue; + } + + char *prefix = device_table[index].prefix; + size_t prefix_len = strlen(prefix); + + if (prefix_len != options[0].len) { + continue; + } + if (strncmp(options[0].value, prefix, prefix_len) != 0) { + continue; + } + + if (gateway_msg_cb[index] == NULL) { + return -ENOENT; + } + /* Delete prefix from path*/ + ret = coap_options_to_path(&options[1], ret - 1, &msg->path); + if (ret < 0) { + return ret; + } + return gateway_msg_cb[index](msg); + } + return -ENOENT; +} + +int lwm2m_register_gw_callback(uint16_t obj_inst_id, lwm2m_engine_gateway_msg_cb cb) +{ + for (int index = 0; index < MAX_INSTANCE_COUNT; index++) { + if (inst[index].obj_inst_id == obj_inst_id) { + gateway_msg_cb[index] = cb; + return 0; + } + } + return -ENOENT; +} + static int lwm2m_gw_init(void) { int ret = 0; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_gateway.h b/subsys/net/lib/lwm2m/lwm2m_obj_gateway.h index 597e3de19bc4a02..0f7a82af2494dee 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_gateway.h +++ b/subsys/net/lib/lwm2m/lwm2m_obj_gateway.h @@ -9,6 +9,8 @@ #ifndef __LWM2M_OBJ_GATEWAY__ #define __LWM2M_OBJ_GATEWAY__ +#include + /* LwM2M Gateway resource IDs */ /* clang-format off */ #define LWM2M_GATEWAY_DEVICE_RID 0 @@ -17,4 +19,42 @@ #define LWM2M_GATEWAY_IOT_DEVICE_OBJECTS_RID 3 /* clang-format on */ +/** + * @brief A callback which handles the prefixed messages from the server. + * + * The callback gets triggered each time the prefix in front of a received lwm2m + * msg path matches the prefix set in the LWM2M_GATEWAY_PREFIX_RID buffer. + * + * It must handle the content of the coap message completely. + * In case of success the LwM2M engine will then send the formatted coap message, + * otherwise a coap response code is sent. + * + * Example of returning CoAP response: + * @code{.c} + * lwm2m_init_message(msg); + * // Write CoAP packet to msg->out.out_cpkt + * return 0; + * @endcode + * + * + * @return 0 if msg contains a valid CoAP response. + * @return negative error code otherwise. + */ +typedef int (*lwm2m_engine_gateway_msg_cb)(struct lwm2m_message *msg); +/** + * @brief Register a callback which handles the prefixed messages from the server. + * + * @return 0 on success + * @return -ENOENT if no object instance with obj_inst_id was found + */ +int lwm2m_register_gw_callback(uint16_t obj_inst_id, lwm2m_engine_gateway_msg_cb cb); +/** + * @brief Check if given message is handled by Gateway callback. + * + * @return 0 if msg was handled by Gateawy and contains a valid response. Negative error code + * otherwise. + * @return -ENOENT if this msg was not handled by Gateway object. + */ +int lwm2m_gw_handle_req(struct lwm2m_message *msg); + #endif /* __LWM2M_OBJ_GATEWAY__ */ diff --git a/subsys/net/lib/lwm2m/lwm2m_rd_client.c b/subsys/net/lib/lwm2m/lwm2m_rd_client.c index 6b3fbcccc6821c2..95b576cb1c6d247 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rd_client.c +++ b/subsys/net/lib/lwm2m/lwm2m_rd_client.c @@ -1132,7 +1132,7 @@ static void sm_registration_done(void) if (sm_is_registered() && (client.trigger_update || now >= next_update())) { - set_sm_state(ENGINE_UPDATE_REGISTRATION); + set_sm_state_delayed(ENGINE_UPDATE_REGISTRATION, DELAY_FOR_ACK); } else if (IS_ENABLED(CONFIG_LWM2M_QUEUE_MODE_ENABLED) && (client.engine_state != ENGINE_REGISTRATION_DONE_RX_OFF) && (now >= next_rx_off())) { diff --git a/subsys/sd/sd_ops.c b/subsys/sd/sd_ops.c index a2934fd856cf512..e77160cea2134a9 100644 --- a/subsys/sd/sd_ops.c +++ b/subsys/sd/sd_ops.c @@ -540,7 +540,7 @@ int card_read_blocks(struct sd_card *card, uint8_t *rbuf, uint32_t start_block, LOG_WRN("SDIO does not support MMC commands"); return -ENOTSUP; } - ret = k_mutex_lock(&card->lock, K_NO_WAIT); + ret = k_mutex_lock(&card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; @@ -704,7 +704,7 @@ int card_write_blocks(struct sd_card *card, const uint8_t *wbuf, uint32_t start_ LOG_WRN("SDIO does not support MMC commands"); return -ENOTSUP; } - ret = k_mutex_lock(&card->lock, K_NO_WAIT); + ret = k_mutex_lock(&card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; diff --git a/subsys/sd/sdio.c b/subsys/sd/sdio.c index ea507fbf49612e6..64c813b1090b090 100644 --- a/subsys/sd/sdio.c +++ b/subsys/sd/sdio.c @@ -792,7 +792,7 @@ int sdio_read_byte(struct sdio_func *func, uint32_t reg, uint8_t *val) LOG_WRN("Card does not support SDIO commands"); return -ENOTSUP; } - ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + ret = k_mutex_lock(&func->card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; @@ -822,7 +822,7 @@ int sdio_write_byte(struct sdio_func *func, uint32_t reg, uint8_t write_val) LOG_WRN("Card does not support SDIO commands"); return -ENOTSUP; } - ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + ret = k_mutex_lock(&func->card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; @@ -855,7 +855,7 @@ int sdio_rw_byte(struct sdio_func *func, uint32_t reg, uint8_t write_val, LOG_WRN("Card does not support SDIO commands"); return -ENOTSUP; } - ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + ret = k_mutex_lock(&func->card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; @@ -889,7 +889,7 @@ int sdio_read_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, LOG_WRN("Card does not support SDIO commands"); return -ENOTSUP; } - ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + ret = k_mutex_lock(&func->card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; @@ -923,7 +923,7 @@ int sdio_write_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, LOG_WRN("Card does not support SDIO commands"); return -ENOTSUP; } - ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + ret = k_mutex_lock(&func->card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; @@ -957,7 +957,7 @@ int sdio_read_blocks_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, LOG_WRN("Card does not support SDIO commands"); return -ENOTSUP; } - ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + ret = k_mutex_lock(&func->card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; @@ -991,7 +991,7 @@ int sdio_write_blocks_fifo(struct sdio_func *func, uint32_t reg, uint8_t *data, LOG_WRN("Card does not support SDIO commands"); return -ENOTSUP; } - ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + ret = k_mutex_lock(&func->card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; @@ -1024,7 +1024,7 @@ int sdio_read_addr(struct sdio_func *func, uint32_t reg, uint8_t *data, LOG_WRN("Card does not support SDIO commands"); return -ENOTSUP; } - ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + ret = k_mutex_lock(&func->card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; @@ -1058,7 +1058,7 @@ int sdio_write_addr(struct sdio_func *func, uint32_t reg, uint8_t *data, LOG_WRN("Card does not support SDIO commands"); return -ENOTSUP; } - ret = k_mutex_lock(&func->card->lock, K_NO_WAIT); + ret = k_mutex_lock(&func->card->lock, K_MSEC(CONFIG_SD_DATA_TIMEOUT)); if (ret) { LOG_WRN("Could not get SD card mutex"); return -EBUSY; diff --git a/subsys/shell/modules/devmem_service.c b/subsys/shell/modules/devmem_service.c index 3c0a42ff3211948..60c51d07faeec7d 100644 --- a/subsys/shell/modules/devmem_service.c +++ b/subsys/shell/modules/devmem_service.c @@ -63,21 +63,13 @@ static int memory_dump(const struct shell *sh, mem_addr_t phys_addr, size_t size hex_data[data_offset] = value; break; case 16: - value = sys_read16(addr + data_offset); - if (IS_ENABLED(CONFIG_BIG_ENDIAN)) { - value = __bswap_16(value); - } - + value = sys_le16_to_cpu(sys_read16(addr + data_offset)); hex_data[data_offset] = (uint8_t)value; value >>= 8; hex_data[data_offset + 1] = (uint8_t)value; break; case 32: - value = sys_read32(addr + data_offset); - if (IS_ENABLED(CONFIG_BIG_ENDIAN)) { - value = __bswap_32(value); - } - + value = sys_le32_to_cpu(sys_read32(addr + data_offset)); hex_data[data_offset] = (uint8_t)value; value >>= 8; hex_data[data_offset + 1] = (uint8_t)value; @@ -192,16 +184,16 @@ static void bypass_cb(const struct shell *sh, uint8_t *recv, size_t len) if (!littleendian) { while (sum > 4) { - *data = __bswap_32(*data); + *data = BSWAP_32(*data); data++; sum = sum - 4; } if (sum % 4 == 0) { - *data = __bswap_32(*data); + *data = BSWAP_32(*data); } else if (sum % 4 == 2) { - *data = __bswap_16(*data); + *data = BSWAP_16(*data); } else if (sum % 4 == 3) { - *data = __bswap_24(*data); + *data = BSWAP_24(*data); } } return; diff --git a/subsys/shell/shell_help.c b/subsys/shell/shell_help.c index 53bf00953c193c8..235e21110322933 100644 --- a/subsys/shell/shell_help.c +++ b/subsys/shell/shell_help.c @@ -139,7 +139,7 @@ static void help_item_print(const struct shell *sh, const char *item_name, z_cursor_next_line_move(sh); return; } else { - z_shell_fprintf(sh, SHELL_NORMAL, "%s:", tabulator); + z_shell_fprintf(sh, SHELL_NORMAL, "%s: ", tabulator); } /* print option help */ formatted_text_print(sh, item_help, offset, false); diff --git a/subsys/testsuite/ztest/CMakeLists.txt b/subsys/testsuite/ztest/CMakeLists.txt index 7817bc2f30b859b..4d29ac033c3b495 100644 --- a/subsys/testsuite/ztest/CMakeLists.txt +++ b/subsys/testsuite/ztest/CMakeLists.txt @@ -26,6 +26,8 @@ zephyr_library_sources_ifdef(CONFIG_ZTRESS src/ztress.c) if(CONFIG_ARCH_POSIX) zephyr_library_sources(src/ztest_posix.c) +elseif(CONFIG_ZTEST_SHELL) + zephyr_library_sources(src/ztest_shell.c) else() zephyr_library_sources(src/ztest_defaults.c) endif() diff --git a/subsys/testsuite/ztest/Kconfig b/subsys/testsuite/ztest/Kconfig index 977f882d838dc9d..e453d2864632476 100644 --- a/subsys/testsuite/ztest/Kconfig +++ b/subsys/testsuite/ztest/Kconfig @@ -23,6 +23,15 @@ config ZTEST_TEST_DELAY_MS Add a delay between between tests to manage output on the console on systems that can't handle the rapid output rate. +config ZTEST_SHELL + bool "Ztest with shell support" + select SHELL + select SHELL_THREAD_PRIORITY_OVERRIDE + select GETOPT_LONG + select SHELL_GETOPT + help + Enable shell to manage test execution and selection. + config ZTEST_CPU_HOLD_TIME_MS int "Time in milliseconds to hold other CPUs for 1cpu type tests" default 3000 diff --git a/subsys/testsuite/ztest/include/zephyr/ztest_test.h b/subsys/testsuite/ztest/include/zephyr/ztest_test.h index aac7a7b2ad8807a..eb6d16cf78422c7 100644 --- a/subsys/testsuite/ztest/include/zephyr/ztest_test.h +++ b/subsys/testsuite/ztest/include/zephyr/ztest_test.h @@ -232,8 +232,11 @@ extern struct ztest_suite_node _ztest_suite_node_list_end[]; * Default entry point for running or listing registered unit tests. * * @param state The current state of the machine as it relates to the test executable. + * @param shuffle Shuffle tests + * @param suite_iter Test suite repetitions. + * @param case_iter Test case repetitions. */ -void ztest_run_all(const void *state); +void ztest_run_all(const void *state, bool shuffle, int suite_iter, int case_iter); /** * The result of the current running test. It's possible that the setup function sets the result @@ -265,18 +268,25 @@ enum ztest_phase { * Run the registered unit tests which return true from their predicate function. * * @param state The current state of the machine as it relates to the test executable. + * @param shuffle Shuffle tests + * @param suite_iter Test suite repetitions. + * @param case_iter Test case repetitions. * @return The number of tests that ran. */ #ifdef ZTEST_UNITTEST -int z_impl_ztest_run_test_suites(const void *state); -static inline int ztest_run_test_suites(const void *state) +int z_impl_ztest_run_test_suites(const void *state, bool shuffle, + int suite_iter, int case_iter); + +static inline int ztest_run_test_suites(const void *state, bool shuffle, + int suite_iter, int case_iter) { - return z_impl_ztest_run_test_suites(state); + return z_impl_ztest_run_test_suites(state, shuffle, suite_iter, case_iter); } #else -__syscall int ztest_run_test_suites(const void *state); +__syscall int ztest_run_test_suites(const void *state, bool shuffle, + int suite_iter, int case_iter); #endif #ifdef ZTEST_UNITTEST @@ -315,9 +325,12 @@ void ztest_verify_all_test_suites_ran(void); * checks for fast failures and initialization. * * @param name The name of the suite to run. + * @param shuffle Shuffle tests + * @param suite_iter Test suite repetitions. + * @param case_iter Test case repetitions. * @return Negative value if the test suite never ran; otherwise, return the number of failures. */ -int z_ztest_run_test_suite(const char *name); +int z_ztest_run_test_suite(const char *name, bool shuffle, int suite_iter, int case_iter); /** * @brief Returns next test within suite. @@ -534,14 +547,15 @@ void ztest_simple_1cpu_after(void *data); * * @param suite Test suite to run. */ -#define ztest_run_test_suite(suite) z_ztest_run_test_suite(STRINGIFY(suite)) +#define ztest_run_test_suite(suite, shuffle, suite_iter, case_iter) \ + z_ztest_run_test_suite(STRINGIFY(suite), shuffle, suite_iter, case_iter) /** * @brief Structure for architecture specific APIs * */ struct ztest_arch_api { - void (*run_all)(const void *state); + void (*run_all)(const void *state, bool shuffle, int suite_iter, int case_iter); bool (*should_suite_run)(const void *state, struct ztest_suite_node *suite); bool (*should_test_run)(const char *suite, const char *test); }; diff --git a/subsys/testsuite/ztest/src/ztest.c b/subsys/testsuite/ztest/src/ztest.c index d49a1ef9c110f8b..5c44829acd426a9 100644 --- a/subsys/testsuite/ztest/src/ztest.c +++ b/subsys/testsuite/ztest/src/ztest.c @@ -18,11 +18,15 @@ static struct k_thread ztest_thread; #endif static bool failed_expectation; +#ifdef CONFIG_ZTEST_SHELL +#include +#endif + #ifdef CONFIG_ZTEST_SHUFFLE #include #include - #include + #define NUM_ITER_PER_SUITE CONFIG_ZTEST_SHUFFLE_SUITE_REPEAT_COUNT #define NUM_ITER_PER_TEST CONFIG_ZTEST_SHUFFLE_TEST_REPEAT_COUNT #else @@ -651,30 +655,33 @@ struct ztest_unit_test *z_ztest_get_next_test(const char *suite, struct ztest_un return NULL; } -#ifdef CONFIG_ZTEST_SHUFFLE -static void z_ztest_shuffle(void *dest[], intptr_t start, size_t num_items, size_t element_size) +#if CONFIG_ZTEST_SHUFFLE +static void z_ztest_shuffle(bool shuffle, void *dest[], intptr_t start, + size_t num_items, size_t element_size) { - void *tmp; - /* Initialize dest array */ for (size_t i = 0; i < num_items; ++i) { dest[i] = (void *)(start + (i * element_size)); } + void *tmp; /* Shuffle dest array */ - for (size_t i = num_items - 1; i > 0; i--) { - int j = sys_rand32_get() % (i + 1); - - if (i != j) { - tmp = dest[j]; - dest[j] = dest[i]; - dest[i] = tmp; + if (shuffle) { + for (size_t i = num_items - 1; i > 0; i--) { + int j = sys_rand32_get() % (i + 1); + + if (i != j) { + tmp = dest[j]; + dest[j] = dest[i]; + dest[i] = tmp; + } } } } -#endif /* CONFIG_ZTEST_SHUFFLE */ +#endif -static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite) +static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite, + bool shuffle, int suite_iter, int case_iter) { struct ztest_unit_test *test = NULL; void *data = NULL; @@ -714,14 +721,13 @@ static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite) data = suite->setup(); } - for (int i = 0; i < NUM_ITER_PER_TEST; i++) { - fail = 0; - + for (int i = 0; i < case_iter; i++) { #ifdef CONFIG_ZTEST_SHUFFLE struct ztest_unit_test *tests_to_run[ZTEST_TEST_COUNT]; memset(tests_to_run, 0, ZTEST_TEST_COUNT * sizeof(struct ztest_unit_test *)); - z_ztest_shuffle((void **)tests_to_run, (intptr_t)_ztest_unit_test_list_start, + z_ztest_shuffle(shuffle, (void **)tests_to_run, + (intptr_t)_ztest_unit_test_list_start, ZTEST_TEST_COUNT, sizeof(struct ztest_unit_test)); for (size_t j = 0; j < ZTEST_TEST_COUNT; ++j) { test = tests_to_run[j]; @@ -771,7 +777,6 @@ static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite) } } #endif - if (test_status == ZTEST_STATUS_OK && fail != 0) { test_status = ZTEST_STATUS_HAS_FAILURE; } @@ -786,9 +791,10 @@ static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite) return fail; } -int z_ztest_run_test_suite(const char *name) +int z_ztest_run_test_suite(const char *name, bool shuffle, int suite_iter, int case_iter) { - return z_ztest_run_test_suite_ptr(ztest_find_test_suite(name)); + return z_ztest_run_test_suite_ptr(ztest_find_test_suite(name), + shuffle, suite_iter, case_iter); } #ifdef CONFIG_USERSPACE @@ -942,14 +948,15 @@ static void __ztest_show_suite_summary(void) flush_log(); } -static int __ztest_run_test_suite(struct ztest_suite_node *ptr, const void *state) +static int __ztest_run_test_suite(struct ztest_suite_node *ptr, + const void *state, bool shuffle, int suite_iter, int case_iter) { struct ztest_suite_stats *stats = ptr->stats; int count = 0; - for (int i = 0; i < NUM_ITER_PER_SUITE; i++) { + for (int i = 0; i < suite_iter; i++) { if (ztest_api.should_suite_run(state, ptr)) { - int fail = z_ztest_run_test_suite_ptr(ptr); + int fail = z_ztest_run_test_suite_ptr(ptr, shuffle, suite_iter, case_iter); count++; stats->run_count++; @@ -962,7 +969,7 @@ static int __ztest_run_test_suite(struct ztest_suite_node *ptr, const void *stat return count; } -int z_impl_ztest_run_test_suites(const void *state) +int z_impl_ztest_run_test_suites(const void *state, bool shuffle, int suite_iter, int case_iter) { int count = 0; @@ -974,31 +981,32 @@ int z_impl_ztest_run_test_suites(const void *state) struct ztest_suite_node *suites_to_run[ZTEST_SUITE_COUNT]; memset(suites_to_run, 0, ZTEST_SUITE_COUNT * sizeof(struct ztest_suite_node *)); - z_ztest_shuffle((void **)suites_to_run, (intptr_t)_ztest_suite_node_list_start, + z_ztest_shuffle(shuffle, (void **)suites_to_run, (intptr_t)_ztest_suite_node_list_start, ZTEST_SUITE_COUNT, sizeof(struct ztest_suite_node)); for (size_t i = 0; i < ZTEST_SUITE_COUNT; ++i) { __ztest_init_unit_test_result_for_suite(suites_to_run[i]); } for (size_t i = 0; i < ZTEST_SUITE_COUNT; ++i) { - count += __ztest_run_test_suite(suites_to_run[i], state); + count += __ztest_run_test_suite(suites_to_run[i], + state, shuffle, suite_iter, case_iter); /* Stop running tests if we have a critical error or if we have a failure and * FAIL_FAST was set */ if (test_status == ZTEST_STATUS_CRITICAL_ERROR || - (test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) { + (test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) { break; } } #else for (struct ztest_suite_node *ptr = _ztest_suite_node_list_start; - ptr < _ztest_suite_node_list_end; ++ptr) { + ptr < _ztest_suite_node_list_end; ++ptr) { __ztest_init_unit_test_result_for_suite(ptr); - count += __ztest_run_test_suite(ptr, state); + count += __ztest_run_test_suite(ptr, state, shuffle, suite_iter, case_iter); /* Stop running tests if we have a critical error or if we have a failure and * FAIL_FAST was set */ if (test_status == ZTEST_STATUS_CRITICAL_ERROR || - (test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) { + (test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) { break; } } @@ -1070,12 +1078,18 @@ void ztest_verify_all_test_suites_ran(void) } } -void ztest_run_all(const void *state) { ztest_api.run_all(state); } +void ztest_run_all(const void *state, bool shuffle, int suite_iter, int case_iter) +{ + ztest_api.run_all(state, shuffle, suite_iter, case_iter); +} void __weak test_main(void) { - ztest_run_all(NULL); - +#if CONFIG_ZTEST_SHUFFLE + ztest_run_all(NULL, true, NUM_ITER_PER_SUITE, NUM_ITER_PER_TEST); +#else + ztest_run_all(NULL, false, NUM_ITER_PER_SUITE, NUM_ITER_PER_TEST); +#endif ztest_verify_all_test_suites_ran(); } @@ -1100,6 +1114,179 @@ int main(void) return test_status; } #else + +/* Shell */ + +#ifdef CONFIG_ZTEST_SHELL +static int cmd_list_suites(const struct shell *sh, size_t argc, char **argv) +{ + struct ztest_suite_node *suite; + + for (suite = _ztest_suite_node_list_start; suite < _ztest_suite_node_list_end; ++suite) { + shell_print(sh, "%s", suite->name); + } + return 0; +} + +static int cmd_list_cases(const struct shell *sh, size_t argc, char **argv) +{ + struct ztest_suite_node *ptr; + struct ztest_unit_test *test = NULL; + int test_count = 0; + + for (ptr = _ztest_suite_node_list_start; ptr < _ztest_suite_node_list_end; ++ptr) { + test = NULL; + while ((test = z_ztest_get_next_test(ptr->name, test)) != NULL) { + shell_print(sh, "%s::%s", test->test_suite_name, test->name); + test_count++; + } + } + return 0; +} +extern void ztest_set_test_args(char *argv); +extern void ztest_reset_test_args(void); + +static int cmd_runall(const struct shell *sh, size_t argc, char **argv) +{ + ztest_reset_test_args(); + ztest_run_all(NULL, false, 1, 1); + end_report(); + return 0; +} + +#ifdef CONFIG_ZTEST_SHUFFLE +static int cmd_shuffle(const struct shell *sh, size_t argc, char **argv) +{ + + struct getopt_state *state; + int opt; + static struct option long_options[] = {{"suite_iter", required_argument, 0, 's'}, + {"case_iter", required_argument, 0, 'c'}, + {0, 0, 0, 0}}; + int opt_index = 0; + int val; + int opt_num = 0; + + int suite_iter = 1; + int case_iter = 1; + + while ((opt = getopt_long(argc, argv, "s:c:", long_options, &opt_index)) != -1) { + state = getopt_state_get(); + switch (opt) { + case 's': + val = atoi(state->optarg); + if (val < 1) { + shell_fprintf(sh, SHELL_ERROR, + "Invalid number of suite interations\n"); + return -ENOEXEC; + } + suite_iter = val; + opt_num++; + break; + case 'c': + val = atoi(state->optarg); + if (val < 1) { + shell_fprintf(sh, SHELL_ERROR, + "Invalid number of case interations\n"); + return -ENOEXEC; + } + case_iter = val; + opt_num++; + break; + default: + shell_fprintf(sh, SHELL_ERROR, + "Invalid option or option usage: %s\n", argv[opt_index + 1]); + return -ENOEXEC; + } + } + ztest_reset_test_args(); + ztest_run_all(NULL, true, suite_iter, case_iter); + end_report(); + return 0; +} +#endif + +static int cmd_run_suite(const struct shell *sh, size_t argc, char **argv) +{ + int count = 0; + bool shuffle = false; + + ztest_set_test_args(argv[1]); + + for (struct ztest_suite_node *ptr = _ztest_suite_node_list_start; + ptr < _ztest_suite_node_list_end; ++ptr) { + __ztest_init_unit_test_result_for_suite(ptr); + count += __ztest_run_test_suite(ptr, NULL, shuffle, 1, 1); + if (test_status == ZTEST_STATUS_CRITICAL_ERROR || + (test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) { + break; + } + } + return 0; +} + +static void testsuite_list_get(size_t idx, struct shell_static_entry *entry); + +SHELL_DYNAMIC_CMD_CREATE(testsuite_names, testsuite_list_get); + +static size_t testsuite_get_all_static(struct ztest_suite_node const **suites) +{ + *suites = _ztest_suite_node_list_start; + return _ztest_suite_node_list_end - _ztest_suite_node_list_start; +} + +static const struct ztest_suite_node *suite_lookup(size_t idx, const char *prefix) +{ + size_t match_idx = 0; + const struct ztest_suite_node *suite; + size_t len = testsuite_get_all_static(&suite); + const struct ztest_suite_node *suite_end = suite + len; + + while (suite < suite_end) { + if ((suite->name != NULL) && (strlen(suite->name) != 0) && + ((prefix == NULL) || + (strncmp(prefix, suite->name, strlen(prefix)) == 0))) { + if (match_idx == idx) { + return suite; + } + ++match_idx; + } + ++suite; + } + + return NULL; +} + +static void testsuite_list_get(size_t idx, struct shell_static_entry *entry) +{ + const struct ztest_suite_node *suite = suite_lookup(idx, ""); + + entry->syntax = (suite != NULL) ? suite->name : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; +} + + SHELL_STATIC_SUBCMD_SET_CREATE( + sub_ztest_cmds, + SHELL_CMD_ARG(run-all, NULL, "Run all tests", cmd_runall, 0, 0), +#ifdef CONFIG_ZTEST_SHUFFLE + SHELL_COND_CMD_ARG(CONFIG_ZTEST_SHUFFLE, shuffle, NULL, + "Shuffle tests", cmd_shuffle, 0, 2), +#endif + SHELL_CMD_ARG(list-testsuites, NULL, + "List all test suites", cmd_list_suites, 0, 0), + SHELL_CMD_ARG(list-testcases, NULL, + "List all test cases", cmd_list_cases, 0, 0), + SHELL_CMD_ARG(run-testsuite, &testsuite_names, + "Run test suite", cmd_run_suite, 2, 0), + SHELL_CMD_ARG(run-testcase, NULL, "Run testcase", cmd_run_suite, 2, 0), + SHELL_SUBCMD_SET_END /* Array terminated. */ + ); + +SHELL_CMD_REGISTER(ztest, &sub_ztest_cmds, "Ztest commands", NULL); +#endif /* CONFIG_ZTEST_SHELL */ + int main(void) { #ifdef CONFIG_USERSPACE @@ -1116,6 +1303,7 @@ int main(void) #endif /* CONFIG_USERSPACE */ z_init_mock(); +#ifndef CONFIG_ZTEST_SHELL test_main(); end_report(); flush_log(); @@ -1152,7 +1340,8 @@ int main(void) ; /* Spin */ } irq_unlock(key); -#endif +#endif /* CONFIG_ZTEST_NO_YIELD */ +#endif /* CONFIG_ZTEST_SHELL */ return 0; } #endif diff --git a/subsys/testsuite/ztest/src/ztest_defaults.c b/subsys/testsuite/ztest/src/ztest_defaults.c index eaf59c8a096c4aa..12569d4126a8cb8 100644 --- a/subsys/testsuite/ztest/src/ztest_defaults.c +++ b/subsys/testsuite/ztest/src/ztest_defaults.c @@ -27,9 +27,9 @@ const char *ztest_relative_filename(const char *file) * * @param state The current state of the machine as it relates to the test executable. */ -void z_ztest_run_all(const void *state) +void z_ztest_run_all(const void *state, bool shuffle, int suite_iter, int case_iter) { - ztest_run_test_suites(state); + ztest_run_test_suites(state, shuffle, suite_iter, case_iter); } /** diff --git a/subsys/testsuite/ztest/src/ztest_new.c b/subsys/testsuite/ztest/src/ztest_new.c deleted file mode 100644 index d49a1ef9c110f8b..000000000000000 --- a/subsys/testsuite/ztest/src/ztest_new.c +++ /dev/null @@ -1,1158 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include -#ifdef CONFIG_USERSPACE -#include -#endif -#include -#include - -#ifdef KERNEL -static struct k_thread ztest_thread; -#endif -static bool failed_expectation; - -#ifdef CONFIG_ZTEST_SHUFFLE -#include -#include - -#include -#define NUM_ITER_PER_SUITE CONFIG_ZTEST_SHUFFLE_SUITE_REPEAT_COUNT -#define NUM_ITER_PER_TEST CONFIG_ZTEST_SHUFFLE_TEST_REPEAT_COUNT -#else -#define NUM_ITER_PER_SUITE 1 -#define NUM_ITER_PER_TEST 1 -#endif - -/* ZTEST_DMEM and ZTEST_BMEM are used for the application shared memory test */ - -/** - * @brief The current status of the test binary - */ -enum ztest_status { - ZTEST_STATUS_OK, - ZTEST_STATUS_HAS_FAILURE, - ZTEST_STATUS_CRITICAL_ERROR -}; - -/** - * @brief Tracks the current phase that ztest is operating in. - */ -ZTEST_DMEM enum ztest_phase cur_phase = TEST_PHASE_FRAMEWORK; - -static ZTEST_BMEM enum ztest_status test_status = ZTEST_STATUS_OK; - -extern ZTEST_DMEM const struct ztest_arch_api ztest_api; - -static void __ztest_show_suite_summary(void); - -static void end_report(void) -{ - __ztest_show_suite_summary(); - if (test_status) { - TC_END_REPORT(TC_FAIL); - } else { - TC_END_REPORT(TC_PASS); - } -} - -static int cleanup_test(struct ztest_unit_test *test) -{ - int ret = TC_PASS; - int mock_status; - - mock_status = z_cleanup_mock(); - -#ifdef KERNEL - /* we need to remove the ztest_thread information from the timeout_q. - * Because we reuse the same k_thread structure this would - * causes some problems. - */ - if (IS_ENABLED(CONFIG_MULTITHREADING)) { - k_thread_abort(&ztest_thread); - } -#endif - - if (!ret && mock_status == 1) { - PRINT("Test %s failed: Unused mock parameter values\n", test->name); - ret = TC_FAIL; - } else if (!ret && mock_status == 2) { - PRINT("Test %s failed: Unused mock return values\n", test->name); - ret = TC_FAIL; - } else { - ; - } - - return ret; -} - -#ifdef KERNEL - -#if defined(CONFIG_SMP) && (CONFIG_MP_MAX_NUM_CPUS > 1) -#define MAX_NUM_CPUHOLD (CONFIG_MP_MAX_NUM_CPUS - 1) -#define CPUHOLD_STACK_SZ (512 + CONFIG_TEST_EXTRA_STACK_SIZE) -static struct k_thread cpuhold_threads[MAX_NUM_CPUHOLD]; -K_KERNEL_STACK_ARRAY_DEFINE(cpuhold_stacks, MAX_NUM_CPUHOLD, CPUHOLD_STACK_SZ); - -static struct k_sem cpuhold_sem; -volatile int cpuhold_active; - -/* "Holds" a CPU for use with the "1cpu" test cases. Note that we - * can't use tools like the cpumask feature because we have tests that - * may need to control that configuration themselves. We do this at - * the lowest level, but locking interrupts directly and spinning. - */ -static void cpu_hold(void *arg1, void *arg2, void *arg3) -{ - ARG_UNUSED(arg1); - ARG_UNUSED(arg2); - ARG_UNUSED(arg3); - - unsigned int key = arch_irq_lock(); - uint32_t dt, start_ms = k_uptime_get_32(); - - k_sem_give(&cpuhold_sem); - -#if (defined(CONFIG_ARM64) || defined(CONFIG_RISCV)) && defined(CONFIG_FPU_SHARING) - /* - * We'll be spinning with IRQs disabled. The flush-your-FPU request - * IPI will never be serviced during that time. Therefore we flush - * the FPU preemptively here to prevent any other CPU waiting after - * this CPU forever and deadlock the system. - */ - k_float_disable(_current_cpu->arch.fpu_owner); -#endif - - while (cpuhold_active) { - k_busy_wait(1000); - } - - /* Holding the CPU via spinning is expensive, and abusing this - * for long-running test cases tends to overload the CI system - * (qemu runs separate CPUs in different threads, but the CI - * logic views it as one "job") and cause other test failures. - */ - dt = k_uptime_get_32() - start_ms; - zassert_true(dt < CONFIG_ZTEST_CPU_HOLD_TIME_MS, - "1cpu test took too long (%d ms)", dt); - arch_irq_unlock(key); -} -#endif /* CONFIG_SMP && (CONFIG_MP_MAX_NUM_CPUS > 1) */ - -void z_impl_z_test_1cpu_start(void) -{ -#if defined(CONFIG_SMP) && (CONFIG_MP_MAX_NUM_CPUS > 1) - unsigned int num_cpus = arch_num_cpus(); - - cpuhold_active = 1; - char tname[CONFIG_THREAD_MAX_NAME_LEN]; - - k_sem_init(&cpuhold_sem, 0, 999); - - /* Spawn N-1 threads to "hold" the other CPUs, waiting for - * each to signal us that it's locked and spinning. - */ - for (int i = 0; i < num_cpus - 1; i++) { - k_thread_create(&cpuhold_threads[i], cpuhold_stacks[i], CPUHOLD_STACK_SZ, - cpu_hold, NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, - 0, K_NO_WAIT); - if (IS_ENABLED(CONFIG_THREAD_NAME)) { - snprintk(tname, CONFIG_THREAD_MAX_NAME_LEN, "cpuhold%02d", i); - k_thread_name_set(&cpuhold_threads[i], tname); - } - k_sem_take(&cpuhold_sem, K_FOREVER); - } -#endif -} - -void z_impl_z_test_1cpu_stop(void) -{ -#if defined(CONFIG_SMP) && (CONFIG_MP_MAX_NUM_CPUS > 1) - unsigned int num_cpus = arch_num_cpus(); - - cpuhold_active = 0; - - for (int i = 0; i < num_cpus - 1; i++) { - k_thread_abort(&cpuhold_threads[i]); - } -#endif -} - -#ifdef CONFIG_USERSPACE -void z_vrfy_z_test_1cpu_start(void) { z_impl_z_test_1cpu_start(); } -#include - -void z_vrfy_z_test_1cpu_stop(void) { z_impl_z_test_1cpu_stop(); } -#include -#endif /* CONFIG_USERSPACE */ -#endif - -__maybe_unused static void run_test_rules(bool is_before, struct ztest_unit_test *test, void *data) -{ - for (struct ztest_test_rule *rule = _ztest_test_rule_list_start; - rule < _ztest_test_rule_list_end; ++rule) { - if (is_before && rule->before_each) { - rule->before_each(test, data); - } else if (!is_before && rule->after_each) { - rule->after_each(test, data); - } - } -} - -static void run_test_functions(struct ztest_suite_node *suite, struct ztest_unit_test *test, - void *data) -{ - __ztest_set_test_phase(TEST_PHASE_TEST); - test->test(data); -} - -COND_CODE_1(KERNEL, (ZTEST_BMEM), ()) static enum ztest_result test_result; - -static int get_final_test_result(const struct ztest_unit_test *test, int ret) -{ - enum ztest_expected_result expected_result = -1; - - for (struct ztest_expected_result_entry *expectation = - _ztest_expected_result_entry_list_start; - expectation < _ztest_expected_result_entry_list_end; ++expectation) { - if (strcmp(expectation->test_name, test->name) == 0 && - strcmp(expectation->test_suite_name, test->test_suite_name) == 0) { - expected_result = expectation->expected_result; - break; - } - } - - if (expected_result == ZTEST_EXPECTED_RESULT_FAIL) { - /* Expected a failure: - * - If we got a failure, return TC_PASS - * - Otherwise force a failure - */ - return (ret == TC_FAIL) ? TC_PASS : TC_FAIL; - } - if (expected_result == ZTEST_EXPECTED_RESULT_SKIP) { - /* Expected a skip: - * - If we got a skip, return TC_PASS - * - Otherwise force a failure - */ - return (ret == TC_SKIP) ? TC_PASS : TC_FAIL; - } - /* No expectation was made, no change is needed. */ - return ret; -} - -/** - * @brief Get a friendly name string for a given test phrase. - * - * @param phase an enum ztest_phase value describing the desired test phase - * @returns a string name for `phase` - */ -static inline const char *get_friendly_phase_name(enum ztest_phase phase) -{ - switch (phase) { - case TEST_PHASE_SETUP: - return "setup"; - case TEST_PHASE_BEFORE: - return "before"; - case TEST_PHASE_TEST: - return "test"; - case TEST_PHASE_AFTER: - return "after"; - case TEST_PHASE_TEARDOWN: - return "teardown"; - case TEST_PHASE_FRAMEWORK: - return "framework"; - default: - return "(unknown)"; - } -} - -static bool current_test_failed_assumption; -void ztest_skip_failed_assumption(void) -{ - if (IS_ENABLED(CONFIG_ZTEST_FAIL_ON_ASSUME)) { - current_test_failed_assumption = true; - } - ztest_test_skip(); -} - -#ifndef KERNEL - -/* Static code analysis tool can raise a violation that the standard header - * shall not be used. - * - * setjmp is using in a test code, not in a runtime code, it is acceptable. - * It is a deliberate deviation. - */ -#include /* parasoft-suppress MISRAC2012-RULE_21_4-a MISRAC2012-RULE_21_4-b*/ -#include -#include -#include - -#define FAIL_FAST 0 - -static jmp_buf test_fail; -static jmp_buf test_pass; -static jmp_buf test_skip; -static jmp_buf stack_fail; -static jmp_buf test_suite_fail; - -void ztest_test_fail(void) -{ - switch (cur_phase) { - case TEST_PHASE_SETUP: - PRINT(" at %s function\n", get_friendly_phase_name(cur_phase)); - longjmp(test_suite_fail, 1); - case TEST_PHASE_BEFORE: - case TEST_PHASE_TEST: - PRINT(" at %s function\n", get_friendly_phase_name(cur_phase)); - longjmp(test_fail, 1); - case TEST_PHASE_AFTER: - case TEST_PHASE_TEARDOWN: - case TEST_PHASE_FRAMEWORK: - PRINT(" ERROR: cannot fail in test phase '%s()', bailing\n", - get_friendly_phase_name(cur_phase)); - longjmp(stack_fail, 1); - } -} - -void ztest_test_pass(void) -{ - if (cur_phase == TEST_PHASE_TEST) { - longjmp(test_pass, 1); - } - PRINT(" ERROR: cannot pass in test phase '%s()', bailing\n", - get_friendly_phase_name(cur_phase)); - longjmp(stack_fail, 1); -} - -void ztest_test_skip(void) -{ - switch (cur_phase) { - case TEST_PHASE_SETUP: - case TEST_PHASE_BEFORE: - case TEST_PHASE_TEST: - longjmp(test_skip, 1); - default: - PRINT(" ERROR: cannot skip in test phase '%s()', bailing\n", - get_friendly_phase_name(cur_phase)); - longjmp(stack_fail, 1); - } -} - -void ztest_test_expect_fail(void) -{ - failed_expectation = true; - - switch (cur_phase) { - case TEST_PHASE_SETUP: - PRINT(" at %s function\n", get_friendly_phase_name(cur_phase)); - break; - case TEST_PHASE_BEFORE: - case TEST_PHASE_TEST: - PRINT(" at %s function\n", get_friendly_phase_name(cur_phase)); - break; - case TEST_PHASE_AFTER: - case TEST_PHASE_TEARDOWN: - case TEST_PHASE_FRAMEWORK: - PRINT(" ERROR: cannot fail in test phase '%s()', bailing\n", - get_friendly_phase_name(cur_phase)); - longjmp(stack_fail, 1); - } -} - -static int run_test(struct ztest_suite_node *suite, struct ztest_unit_test *test, void *data) -{ - int ret = TC_PASS; - - TC_START(test->name); - __ztest_set_test_phase(TEST_PHASE_BEFORE); - - if (test_result == ZTEST_RESULT_SUITE_FAIL) { - ret = TC_FAIL; - goto out; - } - - if (setjmp(test_fail)) { - ret = TC_FAIL; - goto out; - } - - if (setjmp(test_pass)) { - ret = TC_PASS; - goto out; - } - - if (setjmp(test_skip)) { - ret = TC_SKIP; - goto out; - } - - run_test_rules(/*is_before=*/true, test, data); - if (suite->before) { - suite->before(data); - } - run_test_functions(suite, test, data); -out: - if (failed_expectation) { - failed_expectation = false; - ret = TC_FAIL; - } - - __ztest_set_test_phase(TEST_PHASE_AFTER); - if (test_result != ZTEST_RESULT_SUITE_FAIL) { - if (suite->after != NULL) { - suite->after(data); - } - run_test_rules(/*is_before=*/false, test, data); - } - __ztest_set_test_phase(TEST_PHASE_FRAMEWORK); - ret |= cleanup_test(test); - - ret = get_final_test_result(test, ret); - Z_TC_END_RESULT(ret, test->name); - if (ret == TC_SKIP && current_test_failed_assumption) { - test_status = 1; - } - - return ret; -} - -#else /* KERNEL */ - -/* Zephyr's probably going to cause all tests to fail if one test fails, so - * skip the rest of tests if one of them fails - */ -#ifdef CONFIG_ZTEST_FAIL_FAST -#define FAIL_FAST 1 -#else -#define FAIL_FAST 0 -#endif - -K_THREAD_STACK_DEFINE(ztest_thread_stack, CONFIG_ZTEST_STACK_SIZE + CONFIG_TEST_EXTRA_STACK_SIZE); - -static void test_finalize(void) -{ - if (IS_ENABLED(CONFIG_MULTITHREADING)) { - k_thread_abort(&ztest_thread); - if (k_is_in_isr()) { - return; - } - - k_thread_abort(k_current_get()); - CODE_UNREACHABLE; - } -} - -void ztest_test_fail(void) -{ - switch (cur_phase) { - case TEST_PHASE_SETUP: - __ztest_set_test_result(ZTEST_RESULT_SUITE_FAIL); - break; - case TEST_PHASE_BEFORE: - case TEST_PHASE_TEST: - __ztest_set_test_result(ZTEST_RESULT_FAIL); - test_finalize(); - break; - default: - PRINT(" ERROR: cannot fail in test phase '%s()', bailing\n", - get_friendly_phase_name(cur_phase)); - test_status = ZTEST_STATUS_CRITICAL_ERROR; - break; - } -} - -void ztest_test_pass(void) -{ - switch (cur_phase) { - case TEST_PHASE_TEST: - __ztest_set_test_result(ZTEST_RESULT_PASS); - test_finalize(); - break; - default: - PRINT(" ERROR: cannot pass in test phase '%s()', bailing\n", - get_friendly_phase_name(cur_phase)); - test_status = ZTEST_STATUS_CRITICAL_ERROR; - if (cur_phase == TEST_PHASE_BEFORE) { - test_finalize(); - } - } -} - -void ztest_test_skip(void) -{ - switch (cur_phase) { - case TEST_PHASE_SETUP: - __ztest_set_test_result(ZTEST_RESULT_SUITE_SKIP); - break; - case TEST_PHASE_BEFORE: - case TEST_PHASE_TEST: - __ztest_set_test_result(ZTEST_RESULT_SKIP); - test_finalize(); - break; - default: - PRINT(" ERROR: cannot skip in test phase '%s()', bailing\n", - get_friendly_phase_name(cur_phase)); - test_status = ZTEST_STATUS_CRITICAL_ERROR; - break; - } -} - -void ztest_test_expect_fail(void) -{ - failed_expectation = true; -} - -void ztest_simple_1cpu_before(void *data) -{ - ARG_UNUSED(data); - z_test_1cpu_start(); -} - -void ztest_simple_1cpu_after(void *data) -{ - ARG_UNUSED(data); - z_test_1cpu_stop(); -} - -static void test_cb(void *a, void *b, void *c) -{ - struct ztest_suite_node *suite = a; - struct ztest_unit_test *test = b; - const bool config_user_mode = FIELD_GET(K_USER, test->thread_options) != 0; - - if (!IS_ENABLED(CONFIG_USERSPACE) || !k_is_user_context()) { - __ztest_set_test_result(ZTEST_RESULT_PENDING); - run_test_rules(/*is_before=*/true, test, /*data=*/c); - if (suite->before) { - suite->before(/*data=*/c); - } - if (IS_ENABLED(CONFIG_USERSPACE) && config_user_mode) { - k_thread_user_mode_enter(test_cb, a, b, c); - } - } - run_test_functions(suite, test, c); - __ztest_set_test_result(ZTEST_RESULT_PASS); -} - -static int run_test(struct ztest_suite_node *suite, struct ztest_unit_test *test, void *data) -{ - int ret = TC_PASS; - -#if CONFIG_ZTEST_TEST_DELAY_MS > 0 - k_busy_wait(CONFIG_ZTEST_TEST_DELAY_MS * USEC_PER_MSEC); -#endif - TC_START(test->name); - - __ztest_set_test_phase(TEST_PHASE_BEFORE); - - /* If the suite's setup function marked us as skipped, don't bother - * running the tests. - */ - if (IS_ENABLED(CONFIG_MULTITHREADING)) { - get_start_time_cyc(); - k_thread_create(&ztest_thread, ztest_thread_stack, - K_THREAD_STACK_SIZEOF(ztest_thread_stack), - test_cb, suite, test, data, - CONFIG_ZTEST_THREAD_PRIORITY, - K_INHERIT_PERMS, K_FOREVER); - - k_thread_access_grant(&ztest_thread, suite, test, suite->stats); - if (test->name != NULL) { - k_thread_name_set(&ztest_thread, test->name); - } - /* Only start the thread if we're not skipping the suite */ - if (test_result != ZTEST_RESULT_SUITE_SKIP && - test_result != ZTEST_RESULT_SUITE_FAIL) { - k_thread_start(&ztest_thread); - k_thread_join(&ztest_thread, K_FOREVER); - } - } else if (test_result != ZTEST_RESULT_SUITE_SKIP && - test_result != ZTEST_RESULT_SUITE_FAIL) { - __ztest_set_test_result(ZTEST_RESULT_PENDING); - get_start_time_cyc(); - run_test_rules(/*is_before=*/true, test, data); - if (suite->before) { - suite->before(data); - } - run_test_functions(suite, test, data); - } - - __ztest_set_test_phase(TEST_PHASE_AFTER); - if (suite->after != NULL) { - suite->after(data); - } - run_test_rules(/*is_before=*/false, test, data); - - get_test_duration_ms(); - if (tc_spend_time > test->stats->duration_worst_ms) { - test->stats->duration_worst_ms = tc_spend_time; - } - - __ztest_set_test_phase(TEST_PHASE_FRAMEWORK); - - /* Flush all logs in case deferred mode and default logging thread are used. */ - while (IS_ENABLED(CONFIG_TEST_LOGGING_FLUSH_AFTER_TEST) && - IS_ENABLED(CONFIG_LOG_PROCESS_THREAD) && log_data_pending()) { - k_msleep(100); - } - - if (test_result == ZTEST_RESULT_FAIL || test_result == ZTEST_RESULT_SUITE_FAIL || - failed_expectation) { - ret = TC_FAIL; - failed_expectation = false; - } else if (test_result == ZTEST_RESULT_SKIP || test_result == ZTEST_RESULT_SUITE_SKIP) { - ret = TC_SKIP; - } - - if (test_result == ZTEST_RESULT_PASS || !FAIL_FAST) { - ret |= cleanup_test(test); - } - - ret = get_final_test_result(test, ret); - Z_TC_END_RESULT(ret, test->name); - if (ret == TC_SKIP && current_test_failed_assumption) { - test_status = 1; - } - - return ret; -} - -#endif /* !KERNEL */ - -static struct ztest_suite_node *ztest_find_test_suite(const char *name) -{ - struct ztest_suite_node *node; - - for (node = _ztest_suite_node_list_start; node < _ztest_suite_node_list_end; ++node) { - if (strcmp(name, node->name) == 0) { - return node; - } - } - - return NULL; -} - -struct ztest_unit_test *z_ztest_get_next_test(const char *suite, struct ztest_unit_test *prev) -{ - struct ztest_unit_test *test = (prev == NULL) ? _ztest_unit_test_list_start : prev + 1; - - for (; test < _ztest_unit_test_list_end; ++test) { - if (strcmp(suite, test->test_suite_name) == 0) { - return test; - } - } - return NULL; -} - -#ifdef CONFIG_ZTEST_SHUFFLE -static void z_ztest_shuffle(void *dest[], intptr_t start, size_t num_items, size_t element_size) -{ - void *tmp; - - /* Initialize dest array */ - for (size_t i = 0; i < num_items; ++i) { - dest[i] = (void *)(start + (i * element_size)); - } - - /* Shuffle dest array */ - for (size_t i = num_items - 1; i > 0; i--) { - int j = sys_rand32_get() % (i + 1); - - if (i != j) { - tmp = dest[j]; - dest[j] = dest[i]; - dest[i] = tmp; - } - } -} -#endif /* CONFIG_ZTEST_SHUFFLE */ - -static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite) -{ - struct ztest_unit_test *test = NULL; - void *data = NULL; - int fail = 0; - int tc_result = TC_PASS; - - if (FAIL_FAST && test_status != ZTEST_STATUS_OK) { - return test_status; - } - - if (suite == NULL) { - test_status = ZTEST_STATUS_CRITICAL_ERROR; - return -1; - } - -#ifndef KERNEL - if (setjmp(stack_fail)) { - PRINT("TESTSUITE crashed.\n"); - test_status = ZTEST_STATUS_CRITICAL_ERROR; - end_report(); - exit(1); - } -#else - k_object_access_all_grant(&ztest_thread); -#endif - - TC_SUITE_START(suite->name); - current_test_failed_assumption = false; - __ztest_set_test_result(ZTEST_RESULT_PENDING); - __ztest_set_test_phase(TEST_PHASE_SETUP); -#ifndef KERNEL - if (setjmp(test_suite_fail)) { - __ztest_set_test_result(ZTEST_RESULT_SUITE_FAIL); - } -#endif - if (test_result != ZTEST_RESULT_SUITE_FAIL && suite->setup != NULL) { - data = suite->setup(); - } - - for (int i = 0; i < NUM_ITER_PER_TEST; i++) { - fail = 0; - -#ifdef CONFIG_ZTEST_SHUFFLE - struct ztest_unit_test *tests_to_run[ZTEST_TEST_COUNT]; - - memset(tests_to_run, 0, ZTEST_TEST_COUNT * sizeof(struct ztest_unit_test *)); - z_ztest_shuffle((void **)tests_to_run, (intptr_t)_ztest_unit_test_list_start, - ZTEST_TEST_COUNT, sizeof(struct ztest_unit_test)); - for (size_t j = 0; j < ZTEST_TEST_COUNT; ++j) { - test = tests_to_run[j]; - /* Make sure that the test belongs to this suite */ - if (strcmp(suite->name, test->test_suite_name) != 0) { - continue; - } - if (ztest_api.should_test_run(suite->name, test->name)) { - test->stats->run_count++; - tc_result = run_test(suite, test, data); - if (tc_result == TC_PASS) { - test->stats->pass_count++; - } else if (tc_result == TC_SKIP) { - test->stats->skip_count++; - } else if (tc_result == TC_FAIL) { - test->stats->fail_count++; - } - if (tc_result == TC_FAIL) { - fail++; - } - } - - if ((fail && FAIL_FAST) || test_status == ZTEST_STATUS_CRITICAL_ERROR) { - break; - } - } -#else - while (((test = z_ztest_get_next_test(suite->name, test)) != NULL)) { - if (ztest_api.should_test_run(suite->name, test->name)) { - test->stats->run_count++; - tc_result = run_test(suite, test, data); - if (tc_result == TC_PASS) { - test->stats->pass_count++; - } else if (tc_result == TC_SKIP) { - test->stats->skip_count++; - } else if (tc_result == TC_FAIL) { - test->stats->fail_count++; - } - - if (tc_result == TC_FAIL) { - fail++; - } - } - - if ((fail && FAIL_FAST) || test_status == ZTEST_STATUS_CRITICAL_ERROR) { - break; - } - } -#endif - - if (test_status == ZTEST_STATUS_OK && fail != 0) { - test_status = ZTEST_STATUS_HAS_FAILURE; - } - } - - TC_SUITE_END(suite->name, (fail > 0 ? TC_FAIL : TC_PASS)); - __ztest_set_test_phase(TEST_PHASE_TEARDOWN); - if (suite->teardown != NULL) { - suite->teardown(data); - } - - return fail; -} - -int z_ztest_run_test_suite(const char *name) -{ - return z_ztest_run_test_suite_ptr(ztest_find_test_suite(name)); -} - -#ifdef CONFIG_USERSPACE -K_APPMEM_PARTITION_DEFINE(ztest_mem_partition); -#endif - -static void __ztest_init_unit_test_result_for_suite(struct ztest_suite_node *suite) -{ - struct ztest_unit_test *test = NULL; - - while (((test = z_ztest_get_next_test(suite->name, test)) != NULL)) { - test->stats->run_count = 0; - test->stats->skip_count = 0; - test->stats->fail_count = 0; - test->stats->pass_count = 0; - test->stats->duration_worst_ms = 0; - } -} - -static void flush_log(void) -{ - if (IS_ENABLED(CONFIG_LOG_PROCESS_THREAD)) { - while (log_data_pending()) { - k_sleep(K_MSEC(10)); - } - k_sleep(K_MSEC(10)); - } else { - while (LOG_PROCESS()) { - } - } -} - -/* Show one line summary for a test suite. - */ -static void __ztest_show_suite_summary_oneline(struct ztest_suite_node *suite) -{ - int distinct_pass = 0, distinct_fail = 0, distinct_skip = 0, distinct_total = 0; - int effective_total = 0; - int expanded_pass = 0, expanded_passrate = 0; - int passrate_major = 0, passrate_minor = 0, passrate_tail = 0; - int suite_result = TC_PASS; - - struct ztest_unit_test *test = NULL; - unsigned int suite_duration_worst_ms = 0; - - /** summary of disctinct run */ - while (((test = z_ztest_get_next_test(suite->name, test)) != NULL)) { - distinct_total++; - suite_duration_worst_ms += test->stats->duration_worst_ms; - if (test->stats->skip_count == test->stats->run_count) { - distinct_skip++; - } else if (test->stats->pass_count == test->stats->run_count) { - distinct_pass++; - } else { - distinct_fail++; - } - } - - if (distinct_skip == distinct_total) { - suite_result = TC_SKIP; - passrate_major = passrate_minor = 0; - } else { - suite_result = (distinct_fail > 0) ? TC_FAIL : TC_PASS; - effective_total = distinct_total - distinct_skip; - expanded_pass = distinct_pass * 100000; - expanded_passrate = expanded_pass / effective_total; - passrate_major = expanded_passrate / 1000; - passrate_minor = (expanded_passrate - passrate_major * 1000) / 10; - passrate_tail = expanded_passrate - passrate_major * 1000 - passrate_minor * 10; - if (passrate_tail >= 5) { /* rounding */ - passrate_minor++; - } - } - - TC_SUMMARY_PRINT("SUITE %s - %3d.%02d%% [%s]: pass = %d, fail = %d, " - "skip = %d, total = %d duration = %u.%03u seconds\n", - TC_RESULT_TO_STR(suite_result), - passrate_major, passrate_minor, - suite->name, distinct_pass, distinct_fail, - distinct_skip, distinct_total, - suite_duration_worst_ms / 1000, suite_duration_worst_ms % 1000); - flush_log(); -} - -static void __ztest_show_suite_summary_verbose(struct ztest_suite_node *suite) -{ - struct ztest_unit_test *test = NULL; - int tc_result = TC_PASS; - int flush_frequency = 0; - - if (IS_ENABLED(CONFIG_ZTEST_VERBOSE_SUMMARY) == 0) { - return; - } - - while (((test = z_ztest_get_next_test(suite->name, test)) != NULL)) { - if (test->stats->skip_count == test->stats->run_count) { - tc_result = TC_SKIP; - } else if (test->stats->pass_count == test->stats->run_count) { - tc_result = TC_PASS; - } else if (test->stats->pass_count == 0) { - tc_result = TC_FAIL; - } else { - tc_result = TC_FLAKY; - } - - if (tc_result == TC_FLAKY) { - TC_SUMMARY_PRINT(" - %s - [%s.%s] - (Failed %d of %d attempts)" - " - duration = %u.%03u seconds\n", - TC_RESULT_TO_STR(tc_result), - test->test_suite_name, test->name, - test->stats->run_count - test->stats->pass_count, - test->stats->run_count, - test->stats->duration_worst_ms / 1000, - test->stats->duration_worst_ms % 1000); - } else { - TC_SUMMARY_PRINT(" - %s - [%s.%s] duration = %u.%03u seconds\n", - TC_RESULT_TO_STR(tc_result), - test->test_suite_name, test->name, - test->stats->duration_worst_ms / 1000, - test->stats->duration_worst_ms % 1000); - } - - if (flush_frequency % 3 == 0) { - /** Reduce the flush frequencey a bit to speed up the output */ - flush_log(); - } - flush_frequency++; - } - TC_SUMMARY_PRINT("\n"); - flush_log(); -} - -static void __ztest_show_suite_summary(void) -{ - if (IS_ENABLED(CONFIG_ZTEST_SUMMARY) == 0) { - return; - } - /* Flush the log a lot to ensure that no summary content - * is dropped if it goes through the logging subsystem. - */ - flush_log(); - TC_SUMMARY_PRINT("\n------ TESTSUITE SUMMARY START ------\n\n"); - flush_log(); - for (struct ztest_suite_node *ptr = _ztest_suite_node_list_start; - ptr < _ztest_suite_node_list_end; ++ptr) { - - __ztest_show_suite_summary_oneline(ptr); - __ztest_show_suite_summary_verbose(ptr); - } - TC_SUMMARY_PRINT("------ TESTSUITE SUMMARY END ------\n\n"); - flush_log(); -} - -static int __ztest_run_test_suite(struct ztest_suite_node *ptr, const void *state) -{ - struct ztest_suite_stats *stats = ptr->stats; - int count = 0; - - for (int i = 0; i < NUM_ITER_PER_SUITE; i++) { - if (ztest_api.should_suite_run(state, ptr)) { - int fail = z_ztest_run_test_suite_ptr(ptr); - - count++; - stats->run_count++; - stats->fail_count += (fail != 0) ? 1 : 0; - } else { - stats->skip_count++; - } - } - - return count; -} - -int z_impl_ztest_run_test_suites(const void *state) -{ - int count = 0; - - if (test_status == ZTEST_STATUS_CRITICAL_ERROR) { - return count; - } - -#ifdef CONFIG_ZTEST_SHUFFLE - struct ztest_suite_node *suites_to_run[ZTEST_SUITE_COUNT]; - - memset(suites_to_run, 0, ZTEST_SUITE_COUNT * sizeof(struct ztest_suite_node *)); - z_ztest_shuffle((void **)suites_to_run, (intptr_t)_ztest_suite_node_list_start, - ZTEST_SUITE_COUNT, sizeof(struct ztest_suite_node)); - for (size_t i = 0; i < ZTEST_SUITE_COUNT; ++i) { - __ztest_init_unit_test_result_for_suite(suites_to_run[i]); - } - for (size_t i = 0; i < ZTEST_SUITE_COUNT; ++i) { - count += __ztest_run_test_suite(suites_to_run[i], state); - /* Stop running tests if we have a critical error or if we have a failure and - * FAIL_FAST was set - */ - if (test_status == ZTEST_STATUS_CRITICAL_ERROR || - (test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) { - break; - } - } -#else - for (struct ztest_suite_node *ptr = _ztest_suite_node_list_start; - ptr < _ztest_suite_node_list_end; ++ptr) { - __ztest_init_unit_test_result_for_suite(ptr); - count += __ztest_run_test_suite(ptr, state); - /* Stop running tests if we have a critical error or if we have a failure and - * FAIL_FAST was set - */ - if (test_status == ZTEST_STATUS_CRITICAL_ERROR || - (test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) { - break; - } - } -#endif - - return count; -} - -void z_impl___ztest_set_test_result(enum ztest_result new_result) -{ - test_result = new_result; -} - -void z_impl___ztest_set_test_phase(enum ztest_phase new_phase) -{ - cur_phase = new_phase; -} - -#ifdef CONFIG_USERSPACE -void z_vrfy___ztest_set_test_result(enum ztest_result new_result) -{ - z_impl___ztest_set_test_result(new_result); -} -#include - -void z_vrfy___ztest_set_test_phase(enum ztest_phase new_phase) -{ - z_impl___ztest_set_test_phase(new_phase); -} -#include -#endif /* CONFIG_USERSPACE */ - -void ztest_verify_all_test_suites_ran(void) -{ - bool all_tests_run = true; - struct ztest_suite_node *suite; - struct ztest_unit_test *test; - - if (IS_ENABLED(CONFIG_ZTEST_VERIFY_RUN_ALL)) { - for (suite = _ztest_suite_node_list_start; suite < _ztest_suite_node_list_end; - ++suite) { - if (suite->stats->run_count < 1) { - PRINT("ERROR: Test suite '%s' did not run.\n", suite->name); - all_tests_run = false; - } - } - - for (test = _ztest_unit_test_list_start; test < _ztest_unit_test_list_end; ++test) { - suite = ztest_find_test_suite(test->test_suite_name); - if (suite == NULL) { - PRINT("ERROR: Test '%s' assigned to test suite '%s' which doesn't " - "exist\n", - test->name, test->test_suite_name); - all_tests_run = false; - } - } - - if (!all_tests_run) { - test_status = ZTEST_STATUS_HAS_FAILURE; - } - } - - for (test = _ztest_unit_test_list_start; test < _ztest_unit_test_list_end; ++test) { - if (test->stats->fail_count + test->stats->pass_count + test->stats->skip_count != - test->stats->run_count) { - PRINT("Bad stats for %s.%s\n", test->test_suite_name, test->name); - test_status = 1; - } - } -} - -void ztest_run_all(const void *state) { ztest_api.run_all(state); } - -void __weak test_main(void) -{ - ztest_run_all(NULL); - - ztest_verify_all_test_suites_ran(); -} - -#ifndef KERNEL -int main(void) -{ - z_init_mock(); - test_main(); - end_report(); -#ifdef CONFIG_ZTEST_NO_YIELD - /* - * Rather than yielding to idle thread, keep the part awake so debugger can - * still access it, since some SOCs cannot be debugged in low power states. - */ - uint32_t key = irq_lock(); - - while (1) { - ; /* Spin */ - } - irq_unlock(key); -#endif - return test_status; -} -#else -int main(void) -{ -#ifdef CONFIG_USERSPACE - /* Partition containing globals tagged with ZTEST_DMEM and ZTEST_BMEM - * macros. Any variables that user code may reference need to be - * placed in this partition if no other memory domain configuration - * is made. - */ - k_mem_domain_add_partition(&k_mem_domain_default, &ztest_mem_partition); -#ifdef Z_MALLOC_PARTITION_EXISTS - /* Allow access to malloc() memory */ - k_mem_domain_add_partition(&k_mem_domain_default, &z_malloc_partition); -#endif -#endif /* CONFIG_USERSPACE */ - - z_init_mock(); - test_main(); - end_report(); - flush_log(); - LOG_PANIC(); - if (IS_ENABLED(CONFIG_ZTEST_RETEST_IF_PASSED)) { - static __noinit struct { - uint32_t magic; - uint32_t boots; - } state; - const uint32_t magic = 0x152ac523; - - if (state.magic != magic) { - state.magic = magic; - state.boots = 0; - } - state.boots += 1; - if (test_status == 0) { - PRINT("Reset board #%u to test again\n", state.boots); - k_msleep(10); - sys_reboot(SYS_REBOOT_COLD); - } else { - PRINT("Failed after %u attempts\n", state.boots); - state.boots = 0; - } - } -#ifdef CONFIG_ZTEST_NO_YIELD - /* - * Rather than yielding to idle thread, keep the part awake so debugger can - * still access it, since some SOCs cannot be debugged in low power states. - */ - uint32_t key = irq_lock(); - - while (1) { - ; /* Spin */ - } - irq_unlock(key); -#endif - return 0; -} -#endif diff --git a/subsys/testsuite/ztest/src/ztest_posix.c b/subsys/testsuite/ztest/src/ztest_posix.c index d2c1857c04cd449..585bbeb983752b3 100644 --- a/subsys/testsuite/ztest/src/ztest_posix.c +++ b/subsys/testsuite/ztest/src/ztest_posix.c @@ -95,6 +95,8 @@ const char *ztest_get_test_args(void) return test_args; } + + /** * @brief Lists registered unit tests in this binary, one per line * @@ -126,12 +128,12 @@ int z_ztest_list_tests(void) * * @param state The current state of the machine as it relates to the test executable. */ -void z_ztest_run_all(const void *state) +void z_ztest_run_all(const void *state, bool shuffle, int suite_iter, int case_iter) { if (z_ztest_get_list_test()) { z_ztest_list_tests(); } else { - ztest_run_test_suites(state); + ztest_run_test_suites(state, shuffle, suite_iter, case_iter); } } diff --git a/subsys/testsuite/ztest/src/ztest_shell.c b/subsys/testsuite/ztest/src/ztest_shell.c new file mode 100644 index 000000000000000..969f0fcd9d40157 --- /dev/null +++ b/subsys/testsuite/ztest/src/ztest_shell.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2022 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +static const char *test_args; + +/** + * @brief Try to shorten a filename by removing the current directory + * + * This helps to reduce the very long filenames in assertion failures. It + * removes the current directory from the filename and returns the rest. + * This makes assertions a lot more readable, and sometimes they fit on one + * line. + * + * @param file Filename to check + * @returns Shortened filename, or @file if it could not be shortened + */ +const char *ztest_relative_filename(const char *file) +{ + return file; +} + +/** + * Default entry point for running registered unit tests. + * + * @param state The current state of the machine as it relates to the test executable. + */ +void z_ztest_run_all(const void *state, bool shuffle, int suite_iter, int case_iter) +{ + ztest_run_test_suites(state, shuffle, suite_iter, case_iter); +} + +void ztest_reset_test_args(void) +{ + test_args = NULL; +} + +void ztest_set_test_args(char *args) +{ + test_args = strdup(args); +} + +/** + * @brief Helper function to get command line test arguments + * + * @return const char* + */ +char *ztest_get_test_args(void) +{ + if (test_args != NULL) { + return strdup(test_args); + } else { + return NULL; + } +} + + +/** + * @brief Checks if the test_args contains the suite/test name. + * + * @param suite_name + * @param test_name + * @return true + * @return false + */ +static bool z_ztest_testargs_contains(const char *suite_name, const char *test_name) +{ + bool found = false; + char *test_args_local = ztest_get_test_args(); + char *suite_test_pair; + char *last_suite_test_pair; + char *suite_arg; + char *test_arg; + char *last_arg; + + if (test_args_local == NULL) { + return true; + } + suite_test_pair = strtok_r(test_args_local, ",", &last_suite_test_pair); + + while (suite_test_pair && !found) { + suite_arg = strtok_r(suite_test_pair, ":", &last_arg); + test_arg = strtok_r(NULL, ":", &last_arg); + + found = !strcmp(suite_arg, suite_name); + if (test_name && test_arg) { + found &= !strcmp(test_arg, "*") || + !strcmp(test_arg, test_name); + } + + suite_test_pair = strtok_r(NULL, ",", &last_suite_test_pair); + } + return found; +} + +/** + * @brief Determines if the test suite should run based on test cases listed + * in the command line argument. + * + * Overrides implementation in ztest.c + * + * @param state The current state of the machine as it relates to the test + * executable. + * @param suite Pointer to ztest_suite_node + * @return true + * @return false + */ +bool z_ztest_should_suite_run(const void *state, struct ztest_suite_node *suite) +{ + char *test_args_local = ztest_get_test_args(); + bool run_suite = true; + + if (test_args_local != NULL && !z_ztest_testargs_contains(suite->name, NULL)) { + run_suite = false; + suite->stats->run_count++; + } else if (suite->predicate != NULL) { + run_suite = suite->predicate(state); + } + + return run_suite; +} + + + +/** + * @brief Determines if the test case should run based on test cases listed + * in the command line argument. Run all tests for non-posix builds + * + * @param suite - name of test suite + * @param test - name of unit test + * @return true + * @return false + */ +bool z_ztest_should_test_run(const char *suite, const char *test) +{ + bool run_test = false; + + run_test = z_ztest_testargs_contains(suite, test); + + return run_test; +} + +ZTEST_DMEM const struct ztest_arch_api ztest_api = { + .run_all = z_ztest_run_all, + .should_suite_run = z_ztest_should_suite_run, + .should_test_run = z_ztest_should_test_run +}; diff --git a/subsys/usb/device/class/audio/audio.c b/subsys/usb/device/class/audio/audio.c index 338163940e371bd..d293b834cabd77f 100644 --- a/subsys/usb/device/class/audio/audio.c +++ b/subsys/usb/device/class/audio/audio.c @@ -87,7 +87,7 @@ struct dev##_descriptor_##i dev##_desc_##i = { \ .as_interface_alt_0 = INIT_STD_IF(USB_AUDIO_AUDIOSTREAMING, 1, 0, 0), \ .as_interface_alt_1 = INIT_STD_IF(USB_AUDIO_AUDIOSTREAMING, 1, 1, 1), \ .as_cs_interface = INIT_AS_GENERAL(link), \ - .format = INIT_AS_FORMAT_I(CH_CNT(dev, i), GET_RES(dev, i)), \ + .format = INIT_AS_FORMAT_I(CH_CNT(dev, i), GET_RES(dev, i), GET_RATE(dev, i)), \ .std_ep = INIT_STD_AS_AD_EP(dev, i, addr), \ .cs_ep = INIT_CS_AS_AD_EP, \ }; \ @@ -133,7 +133,8 @@ struct dev##_descriptor_##i dev##_desc_##i = { \ 1, 1, 1), \ .as_cs_interface_0 = INIT_AS_GENERAL(id+2), \ .format_0 = INIT_AS_FORMAT_I(CH_CNT(dev##_MIC, i), \ - GET_RES(dev##_MIC, i)), \ + GET_RES(dev##_MIC, i), \ + GET_RATE(dev##_MIC, i)), \ .std_ep_0 = INIT_STD_AS_AD_EP(dev##_MIC, i, \ AUTO_EP_IN), \ .cs_ep_0 = INIT_CS_AS_AD_EP, \ @@ -143,7 +144,8 @@ struct dev##_descriptor_##i dev##_desc_##i = { \ 2, 1, 1), \ .as_cs_interface_1 = INIT_AS_GENERAL(id+3), \ .format_1 = INIT_AS_FORMAT_I(CH_CNT(dev##_HP, i), \ - GET_RES(dev##_HP, i)), \ + GET_RES(dev##_HP, i), \ + GET_RATE(dev##_HP, i)), \ .std_ep_1 = INIT_STD_AS_AD_EP(dev##_HP, i, \ AUTO_EP_OUT), \ .cs_ep_1 = INIT_CS_AS_AD_EP, \ @@ -917,6 +919,7 @@ size_t usb_audio_get_in_frame_size(const struct device *dev) return audio_dev_data->in_frame_size; } +#if (HEADPHONES_DEVICE_COUNT > 0 || HEADSET_DEVICE_COUNT > 0) static void audio_receive_cb(uint8_t ep, enum usb_dc_ep_cb_status_code status) { struct usb_audio_dev_data *audio_dev_data; @@ -968,6 +971,7 @@ static void audio_receive_cb(uint8_t ep, enum usb_dc_ep_cb_status_code status) buffer, ret_bytes); } } +#endif /* #if (HEADPHONES_DEVICE_COUNT > 0 || HEADSET_DEVICE_COUNT > 0) */ void usb_audio_register(const struct device *dev, const struct usb_audio_ops *ops) diff --git a/subsys/usb/device/class/audio/usb_audio_internal.h b/subsys/usb/device/class/audio/usb_audio_internal.h index 7a70ae9417885e2..43c73fd85334aa9 100644 --- a/subsys/usb/device/class/audio/usb_audio_internal.h +++ b/subsys/usb/device/class/audio/usb_audio_internal.h @@ -165,6 +165,18 @@ #define GET_VOLUME_MIC(i, prop) DT_PROP_OR(DT_INST(i, COMPAT_MIC), prop, 0) #define GET_VOLUME(dev, i, prop) GET_VOLUME_##dev(i, prop) +#define GET_RATE_HP(i) DT_PROP(DT_INST(i, COMPAT_HP), sample_rate_hz) +#define GET_RATE_MIC(i) DT_PROP(DT_INST(i, COMPAT_MIC), sample_rate_hz) +#define GET_RATE_HS_HP(i) DT_PROP(DT_INST(i, COMPAT_HS), hp_sample_rate_hz) +#define GET_RATE_HS_MIC(i) DT_PROP(DT_INST(i, COMPAT_HS), mic_sample_rate_hz) +#define GET_RATE(dev, i) GET_RATE_##dev(i) + +#define GET_INTERVAL_HP(i) DT_PROP(DT_INST(i, COMPAT_HP), polling_interval) +#define GET_INTERVAL_MIC(i) DT_PROP(DT_INST(i, COMPAT_MIC), polling_interval) +#define GET_INTERVAL_HS_HP(i) DT_PROP(DT_INST(i, COMPAT_HS), hp_polling_interval) +#define GET_INTERVAL_HS_MIC(i) DT_PROP(DT_INST(i, COMPAT_HS), mic_polling_interval) +#define GET_INTERVAL(dev, i) GET_INTERVAL_##dev(i) + #define SYNC_TYPE_HP(i) 3 #define SYNC_TYPE_MIC(i) DT_ENUM_IDX(DT_INST(i, COMPAT_MIC), sync_type) #define SYNC_TYPE_HS_HP(i) 3 @@ -172,7 +184,7 @@ #define SYNC_TYPE(dev, i) (SYNC_TYPE_##dev(i) << 2) #define EP_SIZE(dev, i) \ - ((GET_RES(dev, i)/8) * CH_CNT(dev, i) * 48) + (DIV_ROUND_UP((GET_RES(dev, i)/8 * CH_CNT(dev, i) * GET_RATE(dev, i)), 1000)) /* *_ID() macros are used to give proper Id to each entity describing * the device. Entities Id must start from 1 that's why 1 is added. @@ -477,11 +489,14 @@ struct dev##_descriptor_##i { \ .wFormatTag = sys_cpu_to_le16(0x0001), \ } +#define SAMPLE_RATE(rate) \ + {(((rate) >> 0) & 0xff), (((rate) >> 8) & 0xff), (((rate) >> 16) & 0xff)} + /** Class-Specific AS Format Type Descriptor 4.5.3 audio10.pdf * For more information refer to 2.2.5 Type I Format Type Descriptor * from frmts10.pdf */ -#define INIT_AS_FORMAT_I(ch_cnt, res) \ +#define INIT_AS_FORMAT_I(ch_cnt, res, rate) \ { \ .bLength = sizeof(struct format_type_i_descriptor), \ .bDescriptorType = USB_DESC_CS_INTERFACE, \ @@ -491,7 +506,7 @@ struct dev##_descriptor_##i { \ .bSubframeSize = res/8, \ .bBitResolution = res, \ .bSamFreqType = 1, \ - .tSamFreq = {0x80, 0xBB, 0x00}, \ + .tSamFreq = SAMPLE_RATE(rate), \ } #define INIT_STD_AS_AD_EP(dev, i, addr) \ @@ -501,7 +516,7 @@ struct dev##_descriptor_##i { \ .bEndpointAddress = addr, \ .bmAttributes = (USB_DC_EP_ISOCHRONOUS | SYNC_TYPE(dev, i)), \ .wMaxPacketSize = sys_cpu_to_le16(EP_SIZE(dev, i)), \ - .bInterval = 0x01, \ + .bInterval = GET_INTERVAL(dev, i), \ .bRefresh = 0x00, \ .bSynchAddress = 0x00, \ } diff --git a/subsys/usb/device_next/usbd_device.c b/subsys/usb/device_next/usbd_device.c index 8046ea12013a4f8..319c73fce2b83e5 100644 --- a/subsys/usb/device_next/usbd_device.c +++ b/subsys/usb/device_next/usbd_device.c @@ -81,8 +81,8 @@ int usbd_device_set_pid(struct usbd_contex *const uds_ctx, } int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx, - const uint8_t class, const uint8_t subclass, - const uint8_t protocol) + const uint8_t base_class, + const uint8_t subclass, const uint8_t protocol) { struct usb_device_descriptor *desc = uds_ctx->desc; int ret = 0; @@ -94,7 +94,7 @@ int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx, goto set_code_triple_exit; } - desc->bDeviceClass = class; + desc->bDeviceClass = base_class; desc->bDeviceSubClass = subclass; desc->bDeviceProtocol = protocol; diff --git a/tests/benchmarks/latency_measure/README.rst b/tests/benchmarks/latency_measure/README.rst index 7f17e979697d74c..7e6f5787ab8d96a 100644 --- a/tests/benchmarks/latency_measure/README.rst +++ b/tests/benchmarks/latency_measure/README.rst @@ -8,14 +8,21 @@ including: * Context switch time between cooperative threads using k_yield * Time to switch from ISR back to interrupted thread * Time from ISR to executing a different thread (rescheduled) -* Times to signal a semaphore then test that semaphore -* Times to signal a semaphore then test that semaphore with a context switch +* Time to signal a semaphore then test that semaphore +* Time to signal a semaphore then test that semaphore with a context switch * Times to lock a mutex then unlock that mutex * Time it takes to create a new thread (without starting it) * Time it takes to start a newly created thread * Time it takes to suspend a thread * Time it takes to resume a suspended thread * Time it takes to abort a thread +* Time it takes to add data to a FIFO/LIFO +* Time it takes to retrieve data from a FIFO/LIFO +* Time it takes to wait on a FIFO/LIFO (and context switch) +* Time it takes to wake and switch to a thread waiting on a FIFO/LIFO +* Time it takes to send and receive events +* Time it takes to wait for events (and context switch) +* Time it takes to wake and switch to a thread waiting for events * Measure average time to alloc memory from heap then free that memory When userspace is enabled using the prj_user.conf configuration file, this benchmark will @@ -29,81 +36,157 @@ threads: Sample output of the benchmark (without userspace enabled):: - *** Booting Zephyr OS build v3.5.0-rc1-139-gdab69aeed11d *** - START - Time Measurement - Timing results: Clock frequency: 120 MHz - Preemptive threads ctx switch via k_yield (K -> K) : 519 cycles , 4325 ns : - Cooperative threads ctx switch via k_yield (K -> K) : 519 cycles , 4325 ns : - Switch from ISR back to interrupted thread : 508 cycles , 4241 ns : - Switch from ISR to another thread (kernel) : 554 cycles , 4616 ns : - Create kernel thread from kernel thread : 396 cycles , 3308 ns : - Start kernel thread from kernel thread : 603 cycles , 5033 ns : - Suspend kernel thread from kernel thread : 599 cycles , 4992 ns : - Resume kernel thread from kernel thread : 547 cycles , 4558 ns : - Abort kernel thread from kernel thread : 339 cycles , 2825 ns : - Give a semaphore (no waiters) from kernel thread : 134 cycles , 1116 ns : - Take a semaphore (no blocking) from kernel thread : 53 cycles , 441 ns : - Take a semaphore (context switch K -> K) : 689 cycles , 5742 ns : - Give a semaphore (context switch K -> K) : 789 cycles , 6575 ns : - Lock a mutex from kernel thread : 94 cycles , 783 ns : - Unlock a mutex from kernel thread : 24 cycles , 200 ns : - Average time for heap malloc : 620 cycles , 5166 ns : - Average time for heap free : 431 cycles , 3591 ns : + *** Booting Zephyr OS build zephyr-v3.5.0-3537-g5dbe0ce2622d *** + THREAD yield.preemptive.ctx.(K -> K) : 344 cycles , 2866 ns : + THREAD yield.cooperative.ctx.(K -> K) : 344 cycles , 2867 ns : + ISR resume.interrupted.thread.kernel : 498 cycles , 4158 ns : + ISR resume.different.thread.kernel : 383 cycles , 3199 ns : + THREAD create.kernel.from.kernel : 401 cycles , 3349 ns : + THREAD start.kernel.from.kernel : 418 cycles , 3491 ns : + THREAD suspend.kernel.from.kernel : 433 cycles , 3616 ns : + THREAD resume.kernel.from.kernel : 351 cycles , 2933 ns : + THREAD abort.kernel.from.kernel : 349 cycles , 2909 ns : + FIFO put.immediate.kernel : 294 cycles , 2450 ns : + FIFO get.immediate.kernel : 135 cycles , 1133 ns : + FIFO put.alloc.immediate.kernel : 906 cycles , 7550 ns : + FIFO get.free.immediate.kernel : 570 cycles , 4750 ns : + FIFO get.blocking.(K -> K) : 545 cycles , 4542 ns : + FIFO put.wake+ctx.(K -> K) : 675 cycles , 5625 ns : + FIFO get.free.blocking.(K -> K) : 555 cycles , 4625 ns : + FIFO put.alloc.wake+ctx.(K -> K) : 670 cycles , 5583 ns : + LIFO put.immediate.kernel : 282 cycles , 2350 ns : + LIFO get.immediate.kernel : 135 cycles , 1133 ns : + LIFO put.alloc.immediate.kernel : 903 cycles , 7526 ns : + LIFO get.free.immediate.kernel : 570 cycles , 4750 ns : + LIFO get.blocking.(K -> K) : 542 cycles , 4524 ns : + LIFO put.wake+ctx.(K -> K) : 670 cycles , 5584 ns : + LIFO get.free.blocking.(K -> K) : 547 cycles , 4558 ns : + LIFO put.alloc.wake+ctx.(K -> K) : 670 cycles , 5583 ns : + EVENTS post.immediate.kernel : 220 cycles , 1833 ns : + EVENTS set.immediate.kernel : 225 cycles , 1875 ns : + EVENTS wait.immediate.kernel : 125 cycles , 1041 ns : + EVENTS wait_all.immediate.kernel : 145 cycles , 1208 ns : + EVENTS wait.blocking.(K -> K) : 594 cycles , 4958 ns : + EVENTS set.wake+ctx.(K -> K) : 774 cycles , 6451 ns : + EVENTS wait_all.blocking.(K -> K) : 605 cycles , 5042 ns : + EVENTS post.wake+ctx.(K -> K) : 785 cycles , 6542 ns : + SEMAPHORE give.immediate.kernel : 165 cycles , 1375 ns : + SEMAPHORE take.immediate.kernel : 69 cycles , 575 ns : + SEMAPHORE take.blocking.(K -> K) : 489 cycles , 4075 ns : + SEMAPHORE give.wake+ctx.(K -> K) : 604 cycles , 5033 ns : + MUTEX lock.immediate.recursive.kernel : 115 cycles , 958 ns : + MUTEX unlock.immediate.recursive.kernel : 40 cycles , 333 ns : + HEAP malloc.immediate : 615 cycles , 5125 ns : + HEAP free.immediate : 431 cycles , 3591 ns : =================================================================== PROJECT EXECUTION SUCCESSFUL Sample output of the benchmark (with userspace enabled):: - *** Booting Zephyr OS build v3.5.0-rc1-139-gdab69aeed11d *** - START - Time Measurement - Timing results: Clock frequency: 120 MHz - Preemptive threads ctx switch via k_yield (K -> K) : 1195 cycles , 9958 ns : - Preemptive threads ctx switch via k_yield (U -> U) : 1485 cycles , 12379 ns : - Preemptive threads ctx switch via k_yield (K -> U) : 1390 cycles , 11587 ns : - Preemptive threads ctx switch via k_yield (U -> K) : 1289 cycles , 10749 ns : - Cooperative threads ctx switch via k_yield (K -> K) : 1185 cycles , 9875 ns : - Cooperative threads ctx switch via k_yield (U -> U) : 1475 cycles , 12295 ns : - Cooperative threads ctx switch via k_yield (K -> U) : 1380 cycles , 11504 ns : - Cooperative threads ctx switch via k_yield (U -> K) : 1280 cycles , 10666 ns : - Switch from ISR back to interrupted thread : 1130 cycles , 9416 ns : - Switch from ISR to another thread (kernel) : 1184 cycles , 9874 ns : - Switch from ISR to another thread (user) : 1390 cycles , 11583 ns : - Create kernel thread from kernel thread : 985 cycles , 8208 ns : - Start kernel thread from kernel thread : 1275 cycles , 10625 ns : - Suspend kernel thread from kernel thread : 1220 cycles , 10167 ns : - Resume kernel thread from kernel thread : 1193 cycles , 9942 ns : - Abort kernel thread from kernel thread : 2555 cycles , 21292 ns : - Create user thread from kernel thread : 849 cycles , 7083 ns : - Start user thread from kernel thread : 6715 cycles , 55960 ns : - Suspend user thread from kernel thread : 1585 cycles , 13208 ns : - Resume user thread from kernel thread : 1383 cycles , 11525 ns : - Abort user thread from kernel thread : 2420 cycles , 20167 ns : - Create user thread from user thread : 2110 cycles , 17584 ns : - Start user thread from user thread : 7070 cycles , 58919 ns : - Suspend user thread from user thread : 1784 cycles , 14874 ns : - Resume user thread from user thread : 1740 cycles , 14502 ns : - Abort user thread from user thread : 3000 cycles , 25000 ns : - Start kernel thread from user thread : 1630 cycles , 13583 ns : - Suspend kernel thread from user thread : 1420 cycles , 11833 ns : - Resume kernel thread from user thread : 1550 cycles , 12917 ns : - Abort kernel thread from user thread : 3135 cycles , 26125 ns : - Give a semaphore (no waiters) from kernel thread : 160 cycles , 1333 ns : - Take a semaphore (no blocking) from kernel thread : 95 cycles , 791 ns : - Give a semaphore (no waiters) from user thread : 380 cycles , 3166 ns : - Take a semaphore (no blocking) from user thread : 315 cycles , 2625 ns : - Take a semaphore (context switch K -> K) : 1340 cycles , 11167 ns : - Give a semaphore (context switch K -> K) : 1460 cycles , 12167 ns : - Take a semaphore (context switch K -> U) : 1540 cycles , 12838 ns : - Give a semaphore (context switch U -> K) : 1800 cycles , 15000 ns : - Take a semaphore (context switch U -> K) : 1690 cycles , 14084 ns : - Give a semaphore (context switch K -> U) : 1650 cycles , 13750 ns : - Take a semaphore (context switch U -> U) : 1890 cycles , 15756 ns : - Give a semaphore (context switch U -> U) : 1990 cycles , 16583 ns : - Lock a mutex from kernel thread : 105 cycles , 875 ns : - Unlock a mutex from kernel thread : 17 cycles , 141 ns : - Lock a mutex from user thread : 330 cycles , 2750 ns : - Unlock a mutex from user thread : 255 cycles , 2125 ns : - Average time for heap malloc : 606 cycles , 5058 ns : - Average time for heap free : 422 cycles , 3516 ns : + *** Booting Zephyr OS build zephyr-v3.5.0-3537-g5dbe0ce2622d *** + THREAD yield.preemptive.ctx.(K -> K) : 990 cycles , 8250 ns : + THREAD yield.preemptive.ctx.(U -> U) : 1285 cycles , 10712 ns : + THREAD yield.preemptive.ctx.(K -> U) : 1178 cycles , 9817 ns : + THREAD yield.preemptive.ctx.(U -> K) : 1097 cycles , 9145 ns : + THREAD yield.cooperative.ctx.(K -> K) : 990 cycles , 8250 ns : + THREAD yield.cooperative.ctx.(U -> U) : 1285 cycles , 10712 ns : + THREAD yield.cooperative.ctx.(K -> U) : 1178 cycles , 9817 ns : + THREAD yield.cooperative.ctx.(U -> K) : 1097 cycles , 9146 ns : + ISR resume.interrupted.thread.kernel : 1120 cycles , 9333 ns : + ISR resume.different.thread.kernel : 1010 cycles , 8417 ns : + ISR resume.different.thread.user : 1207 cycles , 10062 ns : + THREAD create.kernel.from.kernel : 955 cycles , 7958 ns : + THREAD start.kernel.from.kernel : 1095 cycles , 9126 ns : + THREAD suspend.kernel.from.kernel : 1064 cycles , 8874 ns : + THREAD resume.kernel.from.kernel : 999 cycles , 8333 ns : + THREAD abort.kernel.from.kernel : 2280 cycles , 19000 ns : + THREAD create.user.from.kernel : 822 cycles , 6855 ns : + THREAD start.user.from.kernel : 6572 cycles , 54774 ns : + THREAD suspend.user.from.kernel : 1422 cycles , 11857 ns : + THREAD resume.user.from.kernel : 1177 cycles , 9812 ns : + THREAD abort.user.from.kernel : 2147 cycles , 17897 ns : + THREAD create.user.from.user : 2105 cycles , 17542 ns : + THREAD start.user.from.user : 6960 cycles , 58002 ns : + THREAD suspend user.from.user : 1610 cycles , 13417 ns : + THREAD resume user.from.user : 1565 cycles , 13042 ns : + THREAD abort user.from.user : 2780 cycles , 23167 ns : + THREAD start.kernel.from.user : 1482 cycles , 12353 ns : + THREAD suspend.kernel.from.user : 1252 cycles , 10437 ns : + THREAD resume.kernel.from.user : 1387 cycles , 11564 ns : + THREAD abort.kernel.from.user : 2912 cycles , 24272 ns : + FIFO put.immediate.kernel : 314 cycles , 2624 ns : + FIFO get.immediate.kernel : 215 cycles , 1792 ns : + FIFO put.alloc.immediate.kernel : 1025 cycles , 8541 ns : + FIFO get.free.immediate.kernel : 655 cycles , 5458 ns : + FIFO put.alloc.immediate.user : 1740 cycles , 14500 ns : + FIFO get.free.immediate.user : 1410 cycles , 11751 ns : + FIFO get.blocking.(K -> K) : 1249 cycles , 10416 ns : + FIFO put.wake+ctx.(K -> K) : 1320 cycles , 11000 ns : + FIFO get.free.blocking.(K -> K) : 1235 cycles , 10292 ns : + FIFO put.alloc.wake+ctx.(K -> K) : 1355 cycles , 11292 ns : + FIFO get.free.blocking.(U -> K) : 1750 cycles , 14584 ns : + FIFO put.alloc.wake+ctx.(K -> U) : 1680 cycles , 14001 ns : + FIFO get.free.blocking.(K -> U) : 1555 cycles , 12959 ns : + FIFO put.alloc.wake+ctx.(U -> K) : 1845 cycles , 15375 ns : + FIFO get.free.blocking.(U -> U) : 2070 cycles , 17251 ns : + FIFO put.alloc.wake+ctx.(U -> U) : 2170 cycles , 18084 ns : + LIFO put.immediate.kernel : 299 cycles , 2499 ns : + LIFO get.immediate.kernel : 204 cycles , 1708 ns : + LIFO put.alloc.immediate.kernel : 1015 cycles , 8459 ns : + LIFO get.free.immediate.kernel : 645 cycles , 5375 ns : + LIFO put.alloc.immediate.user : 1760 cycles , 14668 ns : + LIFO get.free.immediate.user : 1400 cycles , 11667 ns : + LIFO get.blocking.(K -> K) : 1234 cycles , 10291 ns : + LIFO put.wake+ctx.(K -> K) : 1315 cycles , 10959 ns : + LIFO get.free.blocking.(K -> K) : 1230 cycles , 10251 ns : + LIFO put.alloc.wake+ctx.(K -> K) : 1345 cycles , 11208 ns : + LIFO get.free.blocking.(U -> K) : 1745 cycles , 14544 ns : + LIFO put.alloc.wake+ctx.(K -> U) : 1680 cycles , 14000 ns : + LIFO get.free.blocking.(K -> U) : 1555 cycles , 12958 ns : + LIFO put.alloc.wake+ctx.(U -> K) : 1855 cycles , 15459 ns : + LIFO get.free.blocking.(U -> U) : 2070 cycles , 17251 ns : + LIFO put.alloc.wake+ctx.(U -> U) : 2190 cycles , 18251 ns : + EVENTS post.immediate.kernel : 285 cycles , 2375 ns : + EVENTS set.immediate.kernel : 285 cycles , 2375 ns : + EVENTS wait.immediate.kernel : 215 cycles , 1791 ns : + EVENTS wait_all.immediate.kernel : 215 cycles , 1791 ns : + EVENTS post.immediate.user : 775 cycles , 6459 ns : + EVENTS set.immediate.user : 780 cycles , 6500 ns : + EVENTS wait.immediate.user : 715 cycles , 5959 ns : + EVENTS wait_all.immediate.user : 720 cycles , 6000 ns : + EVENTS wait.blocking.(K -> K) : 1212 cycles , 10108 ns : + EVENTS set.wake+ctx.(K -> K) : 1450 cycles , 12084 ns : + EVENTS wait_all.blocking.(K -> K) : 1260 cycles , 10500 ns : + EVENTS post.wake+ctx.(K -> K) : 1490 cycles , 12417 ns : + EVENTS wait.blocking.(U -> K) : 1577 cycles , 13145 ns : + EVENTS set.wake+ctx.(K -> U) : 1617 cycles , 13479 ns : + EVENTS wait_all.blocking.(U -> K) : 1760 cycles , 14667 ns : + EVENTS post.wake+ctx.(K -> U) : 1790 cycles , 14917 ns : + EVENTS wait.blocking.(K -> U) : 1400 cycles , 11671 ns : + EVENTS set.wake+ctx.(U -> K) : 1812 cycles , 15104 ns : + EVENTS wait_all.blocking.(K -> U) : 1580 cycles , 13167 ns : + EVENTS post.wake+ctx.(U -> K) : 1985 cycles , 16542 ns : + EVENTS wait.blocking.(U -> U) : 1765 cycles , 14709 ns : + EVENTS set.wake+ctx.(U -> U) : 1979 cycles , 16499 ns : + EVENTS wait_all.blocking.(U -> U) : 2080 cycles , 17334 ns : + EVENTS post.wake+ctx.(U -> U) : 2285 cycles , 19043 ns : + SEMAPHORE give.immediate.kernel : 210 cycles , 1750 ns : + SEMAPHORE take.immediate.kernel : 145 cycles , 1208 ns : + SEMAPHORE give.immediate.user : 715 cycles , 5959 ns : + SEMAPHORE take.immediate.user : 660 cycles , 5500 ns : + SEMAPHORE take.blocking.(K -> K) : 1150 cycles , 9584 ns : + SEMAPHORE give.wake+ctx.(K -> K) : 1279 cycles , 10666 ns : + SEMAPHORE take.blocking.(K -> U) : 1343 cycles , 11192 ns : + SEMAPHORE give.wake+ctx.(U -> K) : 1637 cycles , 13645 ns : + SEMAPHORE take.blocking.(U -> K) : 1522 cycles , 12688 ns : + SEMAPHORE give.wake+ctx.(K -> U) : 1472 cycles , 12270 ns : + SEMAPHORE take.blocking.(U -> U) : 1715 cycles , 14296 ns : + SEMAPHORE give.wake+ctx.(U -> U) : 1830 cycles , 15250 ns : + MUTEX lock.immediate.recursive.kernel : 150 cycles , 1250 ns : + MUTEX unlock.immediate.recursive.kernel : 57 cycles , 475 ns : + MUTEX lock.immediate.recursive.user : 670 cycles , 5583 ns : + MUTEX unlock.immediate.recursive.user : 595 cycles , 4959 ns : + HEAP malloc.immediate : 629 cycles , 5241 ns : + HEAP free.immediate : 414 cycles , 3450 ns : =================================================================== PROJECT EXECUTION SUCCESSFUL diff --git a/tests/benchmarks/latency_measure/prj.conf b/tests/benchmarks/latency_measure/prj.conf index a1ca84e4dc1c7e7..89ec3458703af83 100644 --- a/tests/benchmarks/latency_measure/prj.conf +++ b/tests/benchmarks/latency_measure/prj.conf @@ -27,3 +27,6 @@ CONFIG_APPLICATION_DEFINED_SYSCALL=y # Disable time slicing CONFIG_TIMESLICING=n + +# Enable events +CONFIG_EVENTS=y diff --git a/tests/benchmarks/latency_measure/prj_user.conf b/tests/benchmarks/latency_measure/prj_user.conf index 62ce8cafb527f2f..7119db2962dc64d 100644 --- a/tests/benchmarks/latency_measure/prj_user.conf +++ b/tests/benchmarks/latency_measure/prj_user.conf @@ -28,3 +28,6 @@ CONFIG_USERSPACE=y # Disable time slicing CONFIG_TIMESLICING=n + +# Enable events +CONFIG_EVENTS=y diff --git a/tests/benchmarks/latency_measure/src/events.c b/tests/benchmarks/latency_measure/src/events.c new file mode 100644 index 000000000000000..dac6f8ea1fae23f --- /dev/null +++ b/tests/benchmarks/latency_measure/src/events.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * @file measure time for various event operations + * + * This file contains the tests that measure the times for manipulating + * event objects from both kernel and user threads: + * 1. Immediately posting and setting events + * 2. Immediately receiving any or all events. + * 3. Blocking to receive either any or all events. + * 4. Waking (and switching to) a thread waiting for any or all events. + */ + +#include +#include +#include "utils.h" +#include "timing_sc.h" + +#define BENCH_EVENT_SET 0x1234 +#define ALL_EVENTS 0xFFFFFFFF + +static K_EVENT_DEFINE(event_set); + +static void event_ops_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t options = (uint32_t)(uintptr_t)p2; + timing_t start; + timing_t finish; + uint32_t i; + uint64_t cycles; + char description[80]; + + k_event_clear(&event_set, ALL_EVENTS); + + start = timing_timestamp_get(); + for (i = 0; i < num_iterations; i++) { + k_event_post(&event_set, BENCH_EVENT_SET); + } + finish = timing_timestamp_get(); + + snprintf(description, sizeof(description), + "EVENTS post.immediate.%s", + (options & K_USER) ? "user" : "kernel"); + cycles = timing_cycles_get(&start, &finish); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + start = timing_timestamp_get(); + for (i = 0; i < num_iterations; i++) { + k_event_set(&event_set, BENCH_EVENT_SET); + } + finish = timing_timestamp_get(); + + snprintf(description, sizeof(description), + "EVENTS set.immediate.%s", + (options & K_USER) ? "user" : "kernel"); + cycles = timing_cycles_get(&start, &finish); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + start = timing_timestamp_get(); + for (i = 0; i < num_iterations; i++) { + k_event_wait(&event_set, BENCH_EVENT_SET, false, K_FOREVER); + } + finish = timing_timestamp_get(); + + snprintf(description, sizeof(description), + "EVENTS wait.immediate.%s", + (options & K_USER) ? "user" : "kernel"); + cycles = timing_cycles_get(&start, &finish); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + start = timing_timestamp_get(); + for (i = 0; i < num_iterations; i++) { + k_event_wait_all(&event_set, BENCH_EVENT_SET, false, K_FOREVER); + } + finish = timing_timestamp_get(); + + snprintf(description, sizeof(description), + "EVENTS wait_all.immediate.%s", + (options & K_USER) ? "user" : "kernel"); + cycles = timing_cycles_get(&start, &finish); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); +} + +static void start_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t options = (uint32_t)(uintptr_t)p2; + uint32_t alt_options = (uint32_t)(uintptr_t)p3; + uint32_t i; + uint64_t cycles; + char description[80]; + + k_thread_start(&alt_thread); + + for (i = 0; i < num_iterations; i++) { + + /* 2. Set the events to wake alt_thread */ + + timestamp.sample = timing_timestamp_get(); + k_event_set(&event_set, BENCH_EVENT_SET); + } + + snprintf(description, sizeof(description), + "EVENTS wait.blocking.(%c -> %c)", + (alt_options & K_USER) ? 'U' : 'K', + (options & K_USER) ? 'U' : 'K'); + cycles = timestamp.cycles - + timestamp_overhead_adjustment(options, alt_options); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "EVENTS set.wake+ctx.(%c -> %c)", + (options & K_USER) ? 'U' : 'K', + (alt_options & K_USER) ? 'U' : 'K'); + cycles = timestamp.cycles - + timestamp_overhead_adjustment(options, alt_options); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + for (i = 0; i < num_iterations; i++) { + + /* 5. Post the events to wake alt_thread */ + + timestamp.sample = timing_timestamp_get(); + k_event_post(&event_set, BENCH_EVENT_SET); + } + + snprintf(description, sizeof(description), + "EVENTS wait_all.blocking.(%c -> %c)", + (alt_options & K_USER) ? 'U' : 'K', + (options & K_USER) ? 'U' : 'K'); + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "EVENTS post.wake+ctx.(%c -> %c)", + (options & K_USER) ? 'U' : 'K', + (alt_options & K_USER) ? 'U' : 'K'); + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + k_thread_join(&alt_thread, K_FOREVER); +} + +static void alt_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t i; + timing_t start; + timing_t mid; + timing_t finish; + uint64_t sum1 = 0ULL; + uint64_t sum2 = 0ULL; + + for (i = 0; i < num_iterations; i++) { + + /* 1. Wait for any of the events */ + + start = timing_timestamp_get(); + k_event_wait(&event_set, BENCH_EVENT_SET, true, K_FOREVER); + + /* 3. Record the final timestamp */ + + finish = timing_timestamp_get(); + mid = timestamp.sample; + + sum1 += timing_cycles_get(&start, &mid); + sum2 += timing_cycles_get(&mid, &finish); + } + + /* Let start_thread print the results */ + + timestamp.cycles = sum1; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = sum2; + k_sem_take(&pause_sem, K_FOREVER); + + sum1 = 0ULL; + sum2 = 0ULL; + + for (i = 0; i < num_iterations; i++) { + + /* 4. Wait for all of the events */ + + start = timing_timestamp_get(); + k_event_wait_all(&event_set, BENCH_EVENT_SET, true, K_FOREVER); + + /* 6. Record the final timestamp */ + + finish = timing_timestamp_get(); + mid = timestamp.sample; + + sum1 += timing_cycles_get(&start, &mid); + sum2 += timing_cycles_get(&mid, &finish); + } + + /* Let start_thread print the results */ + + timestamp.cycles = sum1; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = sum2; +} + +int event_ops(uint32_t num_iterations, uint32_t options) +{ + int priority; + + priority = k_thread_priority_get(k_current_get()); + + timing_start(); + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + event_ops_entry, + (void *)(uintptr_t)num_iterations, + (void *)(uintptr_t)options, NULL, + priority - 1, options, K_FOREVER); + + k_thread_access_grant(&start_thread, &event_set); + + k_thread_start(&start_thread); + + k_thread_join(&start_thread, K_FOREVER); + + timing_stop(); + + return 0; +} + +int event_blocking_ops(uint32_t num_iterations, uint32_t start_options, + uint32_t alt_options) +{ + int priority; + + priority = k_thread_priority_get(k_current_get()); + + timing_start(); + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + start_thread_entry, + (void *)(uintptr_t)num_iterations, + (void *)(uintptr_t)start_options, + (void *)(uintptr_t)alt_options, + priority - 1, start_options, K_FOREVER); + + k_thread_create(&alt_thread, alt_stack, + K_THREAD_STACK_SIZEOF(alt_stack), + alt_thread_entry, + (void *)(uintptr_t)num_iterations, + (void *)(uintptr_t)alt_options, NULL, + priority - 2, alt_options, K_FOREVER); + + k_thread_access_grant(&start_thread, &alt_thread, &event_set, + &pause_sem); + k_thread_access_grant(&alt_thread, &event_set, &pause_sem); + + k_thread_start(&start_thread); + + k_thread_join(&start_thread, K_FOREVER); + + timing_stop(); + + return 0; +} diff --git a/tests/benchmarks/latency_measure/src/fifo.c b/tests/benchmarks/latency_measure/src/fifo.c new file mode 100644 index 000000000000000..4bd1750e89a4382 --- /dev/null +++ b/tests/benchmarks/latency_measure/src/fifo.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * @file measure time for various FIFO operations + * + * This file contains the tests that measures the times for the following + * FIFO operations from both kernel threads and user threads: + * 1. Immediately adding a data item to a FIFO + * 2. Immediately removing a data item from a FIFO + * 3. Immediately adding a data item to a FIFO with allocation + * 4. Immediately removing a data item from a FIFO with allocation + * 5. Blocking on removing a data item from a FIFO + * 6. Waking (and context switching to) a thread blocked on a FIFO via + * k_fifo_put(). + * 7. Waking (and context switching to) a thread blocked on a FIFO via + * k_fifo_alloc_put(). + */ + +#include +#include +#include "utils.h" +#include "timing_sc.h" + +#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) + +static K_FIFO_DEFINE(fifo); + +BENCH_BMEM uintptr_t fifo_data[5]; + +static void fifo_put_get_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t options = (uint32_t)(uintptr_t)p2; + timing_t start; + timing_t mid; + timing_t finish; + uint64_t put_sum = 0ULL; + uint64_t get_sum = 0ULL; + uintptr_t *data; + + if ((options & K_USER) == 0) { + for (uint32_t i = 0; i < num_iterations; i++) { + start = timing_timestamp_get(); + + k_fifo_put(&fifo, fifo_data); + + mid = timing_timestamp_get(); + + data = k_fifo_get(&fifo, K_NO_WAIT); + + finish = timing_timestamp_get(); + + put_sum += timing_cycles_get(&start, &mid); + get_sum += timing_cycles_get(&mid, &finish); + } + + timestamp.cycles = put_sum; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = get_sum; + k_sem_take(&pause_sem, K_FOREVER); + + put_sum = 0ULL; + get_sum = 0ULL; + } + + for (uint32_t i = 0; i < num_iterations; i++) { + start = timing_timestamp_get(); + + k_fifo_alloc_put(&fifo, fifo_data); + + mid = timing_timestamp_get(); + + data = k_fifo_get(&fifo, K_NO_WAIT); + + finish = timing_timestamp_get(); + + put_sum += timing_cycles_get(&start, &mid); + get_sum += timing_cycles_get(&mid, &finish); + } + + timestamp.cycles = put_sum; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = get_sum; +} + +int fifo_ops(uint32_t num_iterations, uint32_t options) +{ + int priority; + uint64_t cycles; + char description[80]; + + priority = k_thread_priority_get(k_current_get()); + + timing_start(); + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + fifo_put_get_thread_entry, + (void *)(uintptr_t)num_iterations, + (void *)(uintptr_t)options, NULL, + priority - 1, options, K_FOREVER); + + k_thread_access_grant(&start_thread, &pause_sem, &fifo); + + k_thread_start(&start_thread); + + if ((options & K_USER) == 0) { + snprintf(description, sizeof(description), + "FIFO put.immediate.%s", + options & K_USER ? "user" : "kernel"); + + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(options, options); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "FIFO get.immediate.%s", + options & K_USER ? "user" : "kernel"); + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(options, options); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + } + + snprintf(description, sizeof(description), + "FIFO put.alloc.immediate.%s", + options & K_USER ? "user" : "kernel"); + + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "FIFO get.free.immediate.%s", + options & K_USER ? "user" : "kernel"); + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + k_thread_join(&start_thread, K_FOREVER); + + timing_stop(); + + return 0; +} + +static void alt_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t options = (uint32_t)(uintptr_t)p2; + timing_t start; + timing_t mid; + timing_t finish; + uint64_t sum[4] = {0ULL, 0ULL, 0ULL, 0ULL}; + uintptr_t *data; + uint32_t i; + + if ((options & K_USER) == 0) { + + /* Used with k_fifo_put() */ + + for (i = 0; i < num_iterations; i++) { + + /* 1. Block waiting for data on FIFO */ + + start = timing_timestamp_get(); + + data = k_fifo_get(&fifo, K_FOREVER); + + /* 3. Data obtained. */ + + finish = timing_timestamp_get(); + + mid = timestamp.sample; + + sum[0] += timing_cycles_get(&start, &mid); + sum[1] += timing_cycles_get(&mid, &finish); + } + } + + /* Used with k_fifo_alloc_put() */ + + for (i = 0; i < num_iterations; i++) { + + /* 4. Block waiting for data on FIFO */ + + start = timing_timestamp_get(); + + data = k_fifo_get(&fifo, K_FOREVER); + + /* 6. Data obtained */ + + finish = timing_timestamp_get(); + + mid = timestamp.sample; + + sum[2] += timing_cycles_get(&start, &mid); + sum[3] += timing_cycles_get(&mid, &finish); + } + + if ((options & K_USER) == 0) { + timestamp.cycles = sum[0]; + k_sem_take(&pause_sem, K_FOREVER); + timestamp.cycles = sum[1]; + k_sem_take(&pause_sem, K_FOREVER); + } + + timestamp.cycles = sum[2]; + k_sem_take(&pause_sem, K_FOREVER); + timestamp.cycles = sum[3]; +} + +static void start_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t options = (uint32_t)(uintptr_t)p2; + uint32_t i; + + k_thread_start(&alt_thread); + + if ((options & K_USER) == 0) { + for (i = 0; i < num_iterations; i++) { + + /* 2. Add data thereby waking alt thread */ + + timestamp.sample = timing_timestamp_get(); + + k_fifo_put(&fifo, fifo_data); + + } + } + + for (i = 0; i < num_iterations; i++) { + + /* 5. Add data thereby waking alt thread */ + + timestamp.sample = timing_timestamp_get(); + + k_fifo_alloc_put(&fifo, fifo_data); + + } + + k_thread_join(&alt_thread, K_FOREVER); +} + +int fifo_blocking_ops(uint32_t num_iterations, uint32_t start_options, + uint32_t alt_options) +{ + int priority; + uint64_t cycles; + char description[80]; + + priority = k_thread_priority_get(k_current_get()); + + timing_start(); + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + start_thread_entry, + (void *)(uintptr_t)num_iterations, + (void *)(uintptr_t)(start_options | alt_options), NULL, + priority - 1, start_options, K_FOREVER); + + k_thread_create(&alt_thread, alt_stack, + K_THREAD_STACK_SIZEOF(alt_stack), + alt_thread_entry, + (void *)(uintptr_t)num_iterations, + (void *)(uintptr_t)(start_options | alt_options), NULL, + priority - 2, alt_options, K_FOREVER); + + k_thread_access_grant(&start_thread, &alt_thread, &pause_sem, &fifo); + k_thread_access_grant(&alt_thread, &pause_sem, &fifo); + + k_thread_start(&start_thread); + + if (((start_options | alt_options) & K_USER) == 0) { + snprintf(description, sizeof(description), + "FIFO get.blocking.(%s -> %s)", + alt_options & K_USER ? "U" : "K", + start_options & K_USER ? "U" : "K"); + + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "FIFO put.wake+ctx.(%s -> %s)", + start_options & K_USER ? "U" : "K", + alt_options & K_USER ? "U" : "K"); + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + } + + snprintf(description, sizeof(description), + "FIFO get.free.blocking.(%s -> %s)", + alt_options & K_USER ? "U" : "K", + start_options & K_USER ? "U" : "K"); + + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "FIFO put.alloc.wake+ctx.(%s -> %s)", + start_options & K_USER ? "U" : "K", + alt_options & K_USER ? "U" : "K"); + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + k_thread_join(&start_thread, K_FOREVER); + + timing_stop(); + + return 0; +} diff --git a/tests/benchmarks/latency_measure/src/heap_malloc_free.c b/tests/benchmarks/latency_measure/src/heap_malloc_free.c index cdb81e0f5b7cabc..4ff93cdc8063889 100644 --- a/tests/benchmarks/latency_measure/src/heap_malloc_free.c +++ b/tests/benchmarks/latency_measure/src/heap_malloc_free.c @@ -63,9 +63,9 @@ void heap_malloc_free(void) notes = "Memory heap too small--increase it."; } - PRINT_STATS_AVG("Average time for heap malloc", sum_malloc, count, + PRINT_STATS_AVG("HEAP malloc.immediate", sum_malloc, count, failed, notes); - PRINT_STATS_AVG("Average time for heap free", sum_free, count, + PRINT_STATS_AVG("HEAP free.immediate", sum_free, count, failed, notes); timing_stop(); diff --git a/tests/benchmarks/latency_measure/src/int_to_thread.c b/tests/benchmarks/latency_measure/src/int_to_thread.c index ad3cf70fad7185c..62fa8cdca6cf480 100644 --- a/tests/benchmarks/latency_measure/src/int_to_thread.c +++ b/tests/benchmarks/latency_measure/src/int_to_thread.c @@ -174,7 +174,7 @@ int int_to_thread(uint32_t num_iterations) sum -= timestamp_overhead_adjustment(0, 0); - PRINT_STATS_AVG("Switch from ISR back to interrupted thread", + PRINT_STATS_AVG("ISR resume.interrupted.thread.kernel", (uint32_t)sum, num_iterations, false, ""); /* ************** */ @@ -183,7 +183,7 @@ int int_to_thread(uint32_t num_iterations) sum -= timestamp_overhead_adjustment(0, 0); - PRINT_STATS_AVG("Switch from ISR to another thread (kernel)", + PRINT_STATS_AVG("ISR resume.different.thread.kernel", (uint32_t)sum, num_iterations, false, ""); /* ************** */ @@ -193,7 +193,7 @@ int int_to_thread(uint32_t num_iterations) sum -= timestamp_overhead_adjustment(0, K_USER); - PRINT_STATS_AVG("Switch from ISR to another thread (user)", + PRINT_STATS_AVG("ISR resume.different.thread.user", (uint32_t)sum, num_iterations, false, ""); #endif diff --git a/tests/benchmarks/latency_measure/src/lifo.c b/tests/benchmarks/latency_measure/src/lifo.c new file mode 100644 index 000000000000000..052f7b212ffcaa9 --- /dev/null +++ b/tests/benchmarks/latency_measure/src/lifo.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * @file measure time for various LIFO operations + * + * This file contains the tests that measures the times for the following + * LIFO operations from both kernel threads and user threads: + * 1. Immediately adding a data item to a LIFO + * 2. Immediately removing a data item from a LIFO + * 3. Immediately adding a data item to a LIFO with allocation + * 4. Immediately removing a data item from a LIFO with allocation + * 5. Blocking on removing a data item from a LIFO + * 6. Waking (and context switching to) a thread blocked on a LIFO via + * k_lifo_put(). + * 7. Waking (and context switching to) a thread blocked on a LIFO via + * k_lifo_alloc_put(). + */ + +#include +#include +#include "utils.h" +#include "timing_sc.h" + +#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) + +static K_LIFO_DEFINE(lifo); + +BENCH_BMEM uintptr_t lifo_data[5]; + +static void lifo_put_get_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t options = (uint32_t)(uintptr_t)p2; + timing_t start; + timing_t mid; + timing_t finish; + uint64_t put_sum = 0ULL; + uint64_t get_sum = 0ULL; + uintptr_t *data; + + if ((options & K_USER) == 0) { + for (uint32_t i = 0; i < num_iterations; i++) { + start = timing_timestamp_get(); + + k_lifo_put(&lifo, lifo_data); + + mid = timing_timestamp_get(); + + data = k_lifo_get(&lifo, K_NO_WAIT); + + finish = timing_timestamp_get(); + + put_sum += timing_cycles_get(&start, &mid); + get_sum += timing_cycles_get(&mid, &finish); + } + + timestamp.cycles = put_sum; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = get_sum; + k_sem_take(&pause_sem, K_FOREVER); + + put_sum = 0ULL; + get_sum = 0ULL; + } + + for (uint32_t i = 0; i < num_iterations; i++) { + start = timing_timestamp_get(); + + k_lifo_alloc_put(&lifo, lifo_data); + + mid = timing_timestamp_get(); + + data = k_lifo_get(&lifo, K_NO_WAIT); + + finish = timing_timestamp_get(); + + put_sum += timing_cycles_get(&start, &mid); + get_sum += timing_cycles_get(&mid, &finish); + } + + timestamp.cycles = put_sum; + k_sem_take(&pause_sem, K_FOREVER); + + timestamp.cycles = get_sum; +} + +int lifo_ops(uint32_t num_iterations, uint32_t options) +{ + int priority; + uint64_t cycles; + char description[80]; + + priority = k_thread_priority_get(k_current_get()); + + timing_start(); + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + lifo_put_get_thread_entry, + (void *)(uintptr_t)num_iterations, + (void *)(uintptr_t)options, NULL, + priority - 1, options, K_FOREVER); + + k_thread_access_grant(&start_thread, &pause_sem, &lifo); + + k_thread_start(&start_thread); + + if ((options & K_USER) == 0) { + snprintf(description, sizeof(description), + "LIFO put.immediate.%s", + options & K_USER ? "user" : "kernel"); + + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(options, options); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "LIFO get.immediate.%s", + options & K_USER ? "user" : "kernel"); + cycles = timestamp.cycles; + cycles -= timestamp_overhead_adjustment(options, options); + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + } + + snprintf(description, sizeof(description), + "LIFO put.alloc.immediate.%s", + options & K_USER ? "user" : "kernel"); + + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "LIFO get.free.immediate.%s", + options & K_USER ? "user" : "kernel"); + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + k_thread_join(&start_thread, K_FOREVER); + + timing_stop(); + + return 0; +} + +static void alt_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t options = (uint32_t)(uintptr_t)p2; + timing_t start; + timing_t mid; + timing_t finish; + uint64_t sum[4] = {0ULL, 0ULL, 0ULL, 0ULL}; + uintptr_t *data; + uint32_t i; + + if ((options & K_USER) == 0) { + + /* Used with k_lifo_put() */ + + for (i = 0; i < num_iterations; i++) { + + /* 1. Block waiting for data on LIFO */ + + start = timing_timestamp_get(); + + data = k_lifo_get(&lifo, K_FOREVER); + + /* 3. Data obtained. */ + + finish = timing_timestamp_get(); + + mid = timestamp.sample; + + sum[0] += timing_cycles_get(&start, &mid); + sum[1] += timing_cycles_get(&mid, &finish); + } + } + + /* Used with k_lifo_alloc_put() */ + + for (i = 0; i < num_iterations; i++) { + + /* 4. Block waiting for data on LIFO */ + + start = timing_timestamp_get(); + + data = k_lifo_get(&lifo, K_FOREVER); + + /* 6. Data obtained */ + + finish = timing_timestamp_get(); + + mid = timestamp.sample; + + sum[2] += timing_cycles_get(&start, &mid); + sum[3] += timing_cycles_get(&mid, &finish); + } + + if ((options & K_USER) == 0) { + timestamp.cycles = sum[0]; + k_sem_take(&pause_sem, K_FOREVER); + timestamp.cycles = sum[1]; + k_sem_take(&pause_sem, K_FOREVER); + } + + timestamp.cycles = sum[2]; + k_sem_take(&pause_sem, K_FOREVER); + timestamp.cycles = sum[3]; +} + +static void start_thread_entry(void *p1, void *p2, void *p3) +{ + uint32_t num_iterations = (uint32_t)(uintptr_t)p1; + uint32_t options = (uint32_t)(uintptr_t)p2; + uint32_t i; + + k_thread_start(&alt_thread); + + if ((options & K_USER) == 0) { + for (i = 0; i < num_iterations; i++) { + + /* 2. Add data thereby waking alt thread */ + + timestamp.sample = timing_timestamp_get(); + + k_lifo_put(&lifo, lifo_data); + + } + } + + for (i = 0; i < num_iterations; i++) { + + /* 5. Add data thereby waking alt thread */ + + timestamp.sample = timing_timestamp_get(); + + k_lifo_alloc_put(&lifo, lifo_data); + + } + + k_thread_join(&alt_thread, K_FOREVER); +} + +int lifo_blocking_ops(uint32_t num_iterations, uint32_t start_options, + uint32_t alt_options) +{ + int priority; + uint64_t cycles; + char description[80]; + + priority = k_thread_priority_get(k_current_get()); + + timing_start(); + + k_thread_create(&start_thread, start_stack, + K_THREAD_STACK_SIZEOF(start_stack), + start_thread_entry, + (void *)(uintptr_t)num_iterations, + (void *)(uintptr_t)(start_options | alt_options), NULL, + priority - 1, start_options, K_FOREVER); + + k_thread_create(&alt_thread, alt_stack, + K_THREAD_STACK_SIZEOF(alt_stack), + alt_thread_entry, + (void *)(uintptr_t)num_iterations, + (void *)(uintptr_t)(start_options | alt_options), NULL, + priority - 2, alt_options, K_FOREVER); + + k_thread_access_grant(&start_thread, &alt_thread, &pause_sem, &lifo); + k_thread_access_grant(&alt_thread, &pause_sem, &lifo); + + k_thread_start(&start_thread); + + if (((start_options | alt_options) & K_USER) == 0) { + snprintf(description, sizeof(description), + "LIFO get.blocking.(%s -> %s)", + alt_options & K_USER ? "U" : "K", + start_options & K_USER ? "U" : "K"); + + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "LIFO put.wake+ctx.(%s -> %s)", + start_options & K_USER ? "U" : "K", + alt_options & K_USER ? "U" : "K"); + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + } + + snprintf(description, sizeof(description), + "LIFO get.free.blocking.(%s -> %s)", + alt_options & K_USER ? "U" : "K", + start_options & K_USER ? "U" : "K"); + + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + k_sem_give(&pause_sem); + + snprintf(description, sizeof(description), + "LIFO put.alloc.wake+ctx.(%s -> %s)", + start_options & K_USER ? "U" : "K", + alt_options & K_USER ? "U" : "K"); + cycles = timestamp.cycles; + PRINT_STATS_AVG(description, (uint32_t)cycles, + num_iterations, false, ""); + + k_thread_join(&start_thread, K_FOREVER); + + timing_stop(); + + return 0; +} diff --git a/tests/benchmarks/latency_measure/src/main.c b/tests/benchmarks/latency_measure/src/main.c index 499ce1273f11afa..d499e65ad6f1141 100644 --- a/tests/benchmarks/latency_measure/src/main.c +++ b/tests/benchmarks/latency_measure/src/main.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2015 Wind River Systems, Inc. - * Copyright (c) 2023 Intel Corporation. + * Copyright (c) 2023,2024 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,7 +12,6 @@ #include #include -#include #include "utils.h" #include "timing_sc.h" #include @@ -30,7 +29,7 @@ K_APPMEM_PARTITION_DEFINE(bench_mem_partition); #endif K_THREAD_STACK_DEFINE(start_stack, START_STACK_SIZE); -K_THREAD_STACK_DEFINE(alt_stack, START_STACK_SIZE); +K_THREAD_STACK_DEFINE(alt_stack, ALT_STACK_SIZE); K_SEM_DEFINE(pause_sem, 0, 1); @@ -47,6 +46,15 @@ extern void sema_context_switch(uint32_t num_iterations, uint32_t start_options, uint32_t alt_options); extern int thread_ops(uint32_t num_iterations, uint32_t start_options, uint32_t alt_options); +extern int fifo_ops(uint32_t num_iterations, uint32_t options); +extern int fifo_blocking_ops(uint32_t num_iterations, uint32_t start_options, + uint32_t alt_options); +extern int lifo_ops(uint32_t num_iterations, uint32_t options); +extern int lifo_blocking_ops(uint32_t num_iterations, uint32_t start_options, + uint32_t alt_options); +extern int event_ops(uint32_t num_iterations, uint32_t options); +extern int event_blocking_ops(uint32_t num_iterations, uint32_t start_options, + uint32_t alt_options); extern void heap_malloc_free(void); static void test_thread(void *arg1, void *arg2, void *arg3) @@ -90,6 +98,43 @@ static void test_thread(void *arg1, void *arg2, void *arg3) thread_ops(NUM_ITERATIONS, K_USER, 0); #endif + fifo_ops(NUM_ITERATIONS, 0); +#ifdef CONFIG_USERSPACE + fifo_ops(NUM_ITERATIONS, K_USER); +#endif + + fifo_blocking_ops(NUM_ITERATIONS, 0, 0); +#ifdef CONFIG_USERSPACE + fifo_blocking_ops(NUM_ITERATIONS, 0, K_USER); + fifo_blocking_ops(NUM_ITERATIONS, K_USER, 0); + fifo_blocking_ops(NUM_ITERATIONS, K_USER, K_USER); +#endif + + + lifo_ops(NUM_ITERATIONS, 0); +#ifdef CONFIG_USERSPACE + lifo_ops(NUM_ITERATIONS, K_USER); +#endif + + lifo_blocking_ops(NUM_ITERATIONS, 0, 0); +#ifdef CONFIG_USERSPACE + lifo_blocking_ops(NUM_ITERATIONS, 0, K_USER); + lifo_blocking_ops(NUM_ITERATIONS, K_USER, 0); + lifo_blocking_ops(NUM_ITERATIONS, K_USER, K_USER); +#endif + + event_ops(NUM_ITERATIONS, 0); +#ifdef CONFIG_USERSPACE + event_ops(NUM_ITERATIONS, K_USER); +#endif + + event_blocking_ops(NUM_ITERATIONS, 0, 0); +#ifdef CONFIG_USERSPACE + event_blocking_ops(NUM_ITERATIONS, 0, K_USER); + event_blocking_ops(NUM_ITERATIONS, K_USER, 0); + event_blocking_ops(NUM_ITERATIONS, K_USER, K_USER); +#endif + sema_test_signal(NUM_ITERATIONS, 0); #ifdef CONFIG_USERSPACE sema_test_signal(NUM_ITERATIONS, K_USER); diff --git a/tests/benchmarks/latency_measure/src/mutex_lock_unlock.c b/tests/benchmarks/latency_measure/src/mutex_lock_unlock.c index 2f78f45d386ecab..6011f697606d178 100644 --- a/tests/benchmarks/latency_measure/src/mutex_lock_unlock.c +++ b/tests/benchmarks/latency_measure/src/mutex_lock_unlock.c @@ -94,7 +94,7 @@ int mutex_lock_unlock(uint32_t num_iterations, uint32_t options) k_sem_give(&pause_sem); snprintf(description, sizeof(description), - "Lock a mutex from %s thread", + "MUTEX lock.immediate.recursive.%s", (options & K_USER) == K_USER ? "user" : "kernel"); PRINT_STATS_AVG(description, (uint32_t)cycles, num_iterations, false, ""); @@ -102,7 +102,7 @@ int mutex_lock_unlock(uint32_t num_iterations, uint32_t options) cycles = timestamp.cycles; snprintf(description, sizeof(description), - "Unlock a mutex from %s thread", + "MUTEX unlock.immediate.recursive.%s", (options & K_USER) == K_USER ? "user" : "kernel"); PRINT_STATS_AVG(description, (uint32_t)cycles, num_iterations, false, ""); diff --git a/tests/benchmarks/latency_measure/src/sema_test_signal_release.c b/tests/benchmarks/latency_measure/src/sema_test_signal_release.c index 7610200332c0809..bd3078cf42c6f97 100644 --- a/tests/benchmarks/latency_measure/src/sema_test_signal_release.c +++ b/tests/benchmarks/latency_measure/src/sema_test_signal_release.c @@ -139,7 +139,7 @@ void sema_context_switch(uint32_t num_iterations, cycles -= timestamp_overhead_adjustment(start_options, alt_options); snprintf(description, sizeof(description), - "Take a semaphore (context switch %c -> %c)", + "SEMAPHORE take.blocking.(%c -> %c)", ((start_options & K_USER) == K_USER) ? 'U' : 'K', ((alt_options & K_USER) == K_USER) ? 'U' : 'K'); PRINT_STATS_AVG(description, (uint32_t)cycles, @@ -155,7 +155,7 @@ void sema_context_switch(uint32_t num_iterations, cycles -= timestamp_overhead_adjustment(start_options, alt_options); snprintf(description, sizeof(description), - "Give a semaphore (context switch %c -> %c)", + "SEMAPHORE give.wake+ctx.(%c -> %c)", ((alt_options & K_USER) == K_USER) ? 'U' : 'K', ((start_options & K_USER) == K_USER) ? 'U' : 'K'); PRINT_STATS_AVG(description, (uint32_t)cycles, @@ -255,7 +255,7 @@ int sema_test_signal(uint32_t num_iterations, uint32_t options) cycles = timestamp.cycles; snprintf(description, sizeof(description), - "Give a semaphore (no waiters) from %s thread", + "SEMAPHORE give.immediate.%s", (options & K_USER) == K_USER ? "user" : "kernel"); PRINT_STATS_AVG(description, (uint32_t)cycles, @@ -274,7 +274,7 @@ int sema_test_signal(uint32_t num_iterations, uint32_t options) cycles = timestamp.cycles; snprintf(description, sizeof(description), - "Take a semaphore (no blocking) from %s thread", + "SEMAPHORE take.immediate.%s", (options & K_USER) == K_USER ? "user" : "kernel"); PRINT_STATS_AVG(description, (uint32_t)cycles, diff --git a/tests/benchmarks/latency_measure/src/thread.c b/tests/benchmarks/latency_measure/src/thread.c index 4448b0e2304bcc7..99c7c9f534df78b 100644 --- a/tests/benchmarks/latency_measure/src/thread.c +++ b/tests/benchmarks/latency_measure/src/thread.c @@ -248,7 +248,7 @@ int thread_ops(uint32_t num_iterations, uint32_t start_options, uint32_t alt_opt /* Only report stats if created */ snprintf(description, sizeof(description), - "Create %s thread from %s thread", + "THREAD create.%s.from.%s", (alt_options & K_USER) != 0 ? "user" : "kernel", (start_options & K_USER) != 0 ? "user" : "kernel"); @@ -261,7 +261,7 @@ int thread_ops(uint32_t num_iterations, uint32_t start_options, uint32_t alt_opt k_sem_give(&pause_sem); snprintf(description, sizeof(description), - "Start %s thread from %s thread", + "THREAD start.%s.from.%s", (alt_options & K_USER) != 0 ? "user" : "kernel", (start_options & K_USER) != 0 ? "user" : "kernel"); @@ -273,7 +273,7 @@ int thread_ops(uint32_t num_iterations, uint32_t start_options, uint32_t alt_opt k_sem_give(&pause_sem); snprintf(description, sizeof(description), - "Suspend %s thread from %s thread", + "THREAD suspend.%s.from.%s", (alt_options & K_USER) != 0 ? "user" : "kernel", (start_options & K_USER) != 0 ? "user" : "kernel"); @@ -285,7 +285,7 @@ int thread_ops(uint32_t num_iterations, uint32_t start_options, uint32_t alt_opt k_sem_give(&pause_sem); snprintf(description, sizeof(description), - "Resume %s thread from %s thread", + "THREAD resume.%s.from.%s", (alt_options & K_USER) != 0 ? "user" : "kernel", (start_options & K_USER) != 0 ? "user" : "kernel"); @@ -297,7 +297,7 @@ int thread_ops(uint32_t num_iterations, uint32_t start_options, uint32_t alt_opt k_sem_give(&pause_sem); snprintf(description, sizeof(description), - "Abort %s thread from %s thread", + "THREAD abort.%s.from.%s", (alt_options & K_USER) != 0 ? "user" : "kernel", (start_options & K_USER) != 0 ? "user" : "kernel"); diff --git a/tests/benchmarks/latency_measure/src/thread_switch_yield.c b/tests/benchmarks/latency_measure/src/thread_switch_yield.c index 44ccc5932c55127..f0e626d53a7183d 100644 --- a/tests/benchmarks/latency_measure/src/thread_switch_yield.c +++ b/tests/benchmarks/latency_measure/src/thread_switch_yield.c @@ -131,7 +131,7 @@ static void thread_switch_yield_common(const char *description, sum -= timestamp_overhead_adjustment(start_options, alt_options); snprintf(summary, sizeof(summary), - "%s (%c -> %c)", + "%s.(%c -> %c)", description, (start_options & K_USER) == K_USER ? 'U' : 'K', (alt_options & K_USER) == K_USER ? 'U' : 'K'); @@ -148,8 +148,8 @@ void thread_switch_yield(uint32_t num_iterations, bool is_cooperative) : k_thread_priority_get(k_current_get()) - 1; snprintf(description, sizeof(description), - "%s threads ctx switch via k_yield", - is_cooperative ? "Cooperative" : "Preemptive"); + "THREAD yield.%s.ctx", + is_cooperative ? "cooperative" : "preemptive"); /* Kernel -> Kernel */ thread_switch_yield_common(description, num_iterations, 0, 0, diff --git a/tests/benchmarks/latency_measure/src/timing_sc.c b/tests/benchmarks/latency_measure/src/timing_sc.c index 051b9d1810badc9..9397a258b5ab8e6 100644 --- a/tests/benchmarks/latency_measure/src/timing_sc.c +++ b/tests/benchmarks/latency_measure/src/timing_sc.c @@ -11,7 +11,6 @@ */ #include -#include #include "utils.h" #include "timing_sc.h" diff --git a/tests/benchmarks/latency_measure/src/utils.h b/tests/benchmarks/latency_measure/src/utils.h index 62d2fb7259e9fb8..7f3f0bde4e1b9c5 100644 --- a/tests/benchmarks/latency_measure/src/utils.h +++ b/tests/benchmarks/latency_measure/src/utils.h @@ -15,9 +15,10 @@ #include #include #include +#include -#define START_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) -#define ALT_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) +#define START_STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE) +#define ALT_STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE) #ifdef CONFIG_USERSPACE #define BENCH_BMEM K_APP_BMEM(bench_mem_partition) diff --git a/tests/bluetooth/controller/ctrl_conn_update/src/main.c b/tests/bluetooth/controller/ctrl_conn_update/src/main.c index 9e0b07227f13c0c..937f71833346b28 100644 --- a/tests/bluetooth/controller/ctrl_conn_update/src/main.c +++ b/tests/bluetooth/controller/ctrl_conn_update/src/main.c @@ -4194,6 +4194,272 @@ ZTEST(periph_rem, test_conn_update_periph_rem_collision) zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), "Free CTX buffers %d", llcp_ctx_buffers_free()); } + +/* + * (A) + * Central-initiated Connection Parameters Request procedure. + * Central requests change in LE connection parameters, peripheral’s Host accepts. + * + * and + * + * (B) + * Peripheral-initiated Connection Parameters Request procedure. + * Peripheral requests change in LE connection parameters, central’s Host accepts. + * + * NOTE: + * Peripheral-initiated Connection Parameters Request procedure is paused. + * Central-initiated Connection Parameters Request procedure is finished. + * Peripheral-initiated Connection Parameters Request procedure is resumed. + * + * +-----+ +-------+ +-----+ + * | UT | | LL_P | | LT | + * +-----+ +-------+ +-----+ + * | | | + * | LE Connection Update | | + * |-------------------------->| | (B) + * | | LL_CONNECTION_PARAM_REQ | + * | |<--------------------------| (A) + * | | LL_CONNECTION_PARAM_REQ | + * | |-------------------------->| (B) + * | | | + * | | | + * | | | + * | LE Remote Connection | | + * | Parameter Request | | + * |<--------------------------| | (A) + * | LE Remote Connection | | + * | Parameter Request | | + * | Reply | | + * |-------------------------->| | (A) + * | | LL_REJECT_EXT_IND | + * | |<--------------------------| (B) + * | | | + * | LE Connection Update | | + * | Complete (collision) | | + * |<--------------------------| | (B) + * | | LL_CONNECTION_PARAM_RSP | + * | |-------------------------->| (A) + * | | | + * | LE Connection Update | | + * |-------------------------->| | (B) + * | | | + * | <------------------------> | + * | < LOCAL PROCEDURE PAUSED > | + * | <------------------------> | + * | | | + * | | LL_CONNECTION_UPDATE_IND | + * | |<--------------------------| (A) + * | | | + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * | | | + * | LE Connection Update | | + * | Complete | | + * |<--------------------------| | (A) + * | | | + * | <-------------------------> | + * | < LOCAL PROCEDURE RESUMED > | + * | <-------------------------> | + * | | | + * | | LL_CONNECTION_PARAM_REQ | + * | |-------------------------->| (B) + * | | | + * | | LL_CONNECTION_UPDATE_IND | + * | |<--------------------------| (B) + * | | | + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * | | | + * | LE Connection Update | | + * | Complete | | + * |<--------------------------| | (B) + * | | | + */ +ZTEST(periph_rem, test_conn_update_periph_rem_late_collision) +{ + uint8_t err; + struct node_tx *tx; + struct node_rx_pdu *ntf; + uint16_t instant; + struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = { + .reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ, + .error_code = BT_HCI_ERR_LL_PROC_COLLISION + }; + struct node_rx_pu cu1 = { .status = BT_HCI_ERR_LL_PROC_COLLISION }; + struct node_rx_pu cu = { .status = BT_HCI_ERR_SUCCESS }; + + /* Role */ + test_set_role(&conn, BT_HCI_ROLE_PERIPHERAL); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /*******************/ + + /* (B) Initiate a Connection Parameter Request Procedure */ + err = ull_cp_conn_update(&conn, req_B->interval_min, req_B->interval_max, req_B->latency, + req_B->timeout, NULL); + zassert_equal(err, BT_HCI_ERR_SUCCESS); + + /* Prepare */ + event_prepare(&conn); + + /*******************/ + + /* (A) Rx */ + lt_tx(LL_CONNECTION_PARAM_REQ, &conn, &conn_param_req); + + /* Done */ + event_done(&conn); + + /*******************/ + + /* Prepare */ + event_prepare(&conn); + + /* (B) Tx Queue should have one LL Control PDU */ + req_B->reference_conn_event_count = event_counter(&conn) - 1; + lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, req_B); + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /*******************/ + /* (A) There should be one host notification */ + ut_rx_pdu(LL_CONNECTION_PARAM_REQ, &ntf, &conn_param_req); + ut_rx_q_is_empty(); + + /* Release Ntf */ + release_ntf(ntf); + + /*******************/ + /* Rx */ + lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind); + + /* (A) */ + ull_cp_conn_param_req_reply(&conn); + + /*******************/ + + /* Prepare */ + event_prepare(&conn); + conn_param_rsp.reference_conn_event_count = conn_param_req.reference_conn_event_count; + + /* (A) Tx Queue should have one LL Control PDU */ + lt_rx(LL_CONNECTION_PARAM_RSP, &conn, &tx, &conn_param_rsp); + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* (A) There should be one host notification */ + ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu1); + ut_rx_q_is_empty(); + + /* Release Ntf */ + release_ntf(ntf); + + /* (B) Initiate a Connection Parameter Request Procedure */ + err = ull_cp_conn_update(&conn, req_B->interval_min, req_B->interval_max, req_B->latency, + req_B->timeout, NULL); + + /* Prepare */ + event_prepare(&conn); + /* Done */ + event_done(&conn); + + + /* (A) Rx */ + conn_update_ind.instant = event_counter(&conn) + 6U; + instant = conn_update_ind.instant; + lt_tx(LL_CONNECTION_UPDATE_IND, &conn, &conn_update_ind); + /* Prepare */ + event_prepare(&conn); + + /* Done */ + event_done(&conn); + + /* Release Tx */ + ull_cp_release_tx(&conn, tx); + + /* */ + while (!is_instant_reached(&conn, instant)) { + /* Prepare */ + event_prepare(&conn); + + /* (A) Tx Queue should NOT have a LL Control PDU */ + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* (A) There should NOT be a host notification */ + ut_rx_q_is_empty(); + } + + /* Prepare */ + event_prepare(&conn); + + /* (B) Tx Queue should have one LL Control PDU */ + req_B->reference_conn_event_count = event_counter(&conn) - 1; + lt_rx(LL_CONNECTION_PARAM_REQ, &conn, &tx, req_B); + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* (A) There should be one host notification */ + ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu); + ut_rx_q_is_empty(); + + /* Release Ntf */ + release_ntf(ntf); + + /* Prepare */ + event_prepare(&conn); + + /* (B) Tx Queue should NOT have a LL Control PDU */ + lt_rx_q_is_empty(&conn); + + /* (B) Rx */ + cu_ind_B->instant = instant = event_counter(&conn) + 6; + lt_tx(LL_CONNECTION_UPDATE_IND, &conn, cu_ind_B); + + /* Done */ + event_done(&conn); + + /* */ + while (!is_instant_reached(&conn, instant)) { + /* Prepare */ + event_prepare(&conn); + + /* (B) Tx Queue should NOT have a LL Control PDU */ + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* (B) There should NOT be a host notification */ + ut_rx_q_is_empty(); + } + + /* Prepare */ + event_prepare(&conn); + + /* (B) Tx Queue should NOT have a LL Control PDU */ + lt_rx_q_is_empty(&conn); + + /* Done */ + event_done(&conn); + + /* (B) There should be one host notification */ + ut_rx_node(NODE_CONN_UPDATE, &ntf, &cu); + ut_rx_q_is_empty(); + + /* Release Ntf */ + release_ntf(ntf); + zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), + "Free CTX buffers %d", llcp_ctx_buffers_free()); +} #else /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ /* diff --git a/tests/bluetooth/host/keys/bt_keys_get_addr/src/main.c b/tests/bluetooth/host/keys/bt_keys_get_addr/src/main.c index 0621346318157ed..cebbf1923e9187c 100644 --- a/tests/bluetooth/host/keys/bt_keys_get_addr/src/main.c +++ b/tests/bluetooth/host/keys/bt_keys_get_addr/src/main.c @@ -181,11 +181,11 @@ void test_main(void) { /* Only startup suite will run. */ all_startup_checks_executed = false; - ztest_run_all(NULL); + ztest_run_all(NULL, false, 1, 1); /* All other suites, except startup suite, will run. */ all_startup_checks_executed = true; - ztest_run_all(NULL); + ztest_run_all(NULL, false, 1, 1); /* Check that all the suites in this binary ran at least once. */ ztest_verify_all_test_suites_ran(); diff --git a/tests/bluetooth/shell/audio.conf b/tests/bluetooth/shell/audio.conf index 0458bcb82b19d29..0a38138b6aeca67 100644 --- a/tests/bluetooth/shell/audio.conf +++ b/tests/bluetooth/shell/audio.conf @@ -162,6 +162,9 @@ CONFIG_BT_CAP_COMMANDER=y # Telephone and Media Audio Profile CONFIG_BT_TMAP=y +# Public Broadcast Profile +CONFIG_BT_PBP=y + CONFIG_BT_PACS_SUPPORTED_CONTEXT_NOTIFIABLE=y CONFIG_BT_PAC_SNK_LOC_NOTIFIABLE=y CONFIG_BT_PAC_SRC_LOC_NOTIFIABLE=y diff --git a/tests/bluetooth/tester/overlay-le-audio.conf b/tests/bluetooth/tester/overlay-le-audio.conf index 330ea3c6b997d7c..eb2abbf1a684f41 100644 --- a/tests/bluetooth/tester/overlay-le-audio.conf +++ b/tests/bluetooth/tester/overlay-le-audio.conf @@ -98,7 +98,9 @@ CONFIG_BT_CSIP_SET_MEMBER=y # CCP CONFIG_BT_ATT_TX_COUNT=12 CONFIG_BT_TBS_CLIENT_GTBS=y -CONFIG_BT_TBS_CLIENT_TBS=n +CONFIG_BT_TBS_CLIENT_TBS=y +CONFIG_BT_TBS_CLIENT_CCID=y +CONFIG_BT_TBS_CLIENT_MAX_CALLS=2 # CAS CONFIG_BT_CAP_ACCEPTOR=y diff --git a/tests/bluetooth/tester/src/btp/btp_ccp.h b/tests/bluetooth/tester/src/btp/btp_ccp.h index 1792637de2ef98b..cfaee2bf8bfec5d 100644 --- a/tests/bluetooth/tester/src/btp/btp_ccp.h +++ b/tests/bluetooth/tester/src/btp/btp_ccp.h @@ -46,6 +46,113 @@ struct btp_ccp_read_call_state_cmd { uint8_t inst_index; } __packed; +#define BTP_CCP_READ_BEARER_NAME 0x07 +struct btp_ccp_read_bearer_name_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_BEARER_UCI 0x08 +struct btp_ccp_read_bearer_uci_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_BEARER_TECH 0x09 +struct btp_ccp_read_bearer_technology_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_URI_LIST 0x0a +struct btp_ccp_read_uri_list_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_SIGNAL_STRENGTH 0x0b +struct btp_ccp_read_signal_strength_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_SIGNAL_INTERVAL 0x0c +struct btp_ccp_read_signal_interval_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_CURRENT_CALLS 0x0d +struct btp_ccp_read_current_calls_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_CCID 0x0e +struct btp_ccp_read_ccid_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_CALL_URI 0x0f +struct btp_ccp_read_call_uri_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_STATUS_FLAGS 0x10 +struct btp_ccp_read_status_flags_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_OPTIONAL_OPCODES 0x11 +struct btp_ccp_read_optional_opcodes_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_FRIENDLY_NAME 0x12 +struct btp_ccp_read_friendly_name_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_READ_REMOTE_URI 0x13 +struct btp_ccp_read_remote_uri_cmd { + bt_addr_le_t address; + uint8_t inst_index; +} __packed; + +#define BTP_CCP_SET_SIGNAL_INTERVAL 0x14 +struct btp_ccp_set_signal_interval_cmd { + bt_addr_le_t address; + uint8_t inst_index; + uint8_t interval; +} __packed; + +#define BTP_CCP_HOLD_CALL 0x15 +struct btp_ccp_hold_call_cmd { + bt_addr_le_t address; + uint8_t inst_index; + uint8_t call_id; +} __packed; + +#define BTP_CCP_RETRIEVE_CALL 0x16 +struct btp_ccp_retrieve_call_cmd { + bt_addr_le_t address; + uint8_t inst_index; + uint8_t call_id; +} __packed; + +#define BTP_CCP_JOIN_CALLS 0x17 +struct btp_ccp_join_calls_cmd { + bt_addr_le_t address; + uint8_t inst_index; + uint8_t count; + uint8_t call_index[]; +} __packed; + /* CCP events */ #define BTP_CCP_EV_DISCOVERED 0x80 struct btp_ccp_discovered_ev { @@ -61,3 +168,52 @@ struct btp_ccp_call_states_ev { uint8_t call_count; struct bt_tbs_client_call_state call_states[0]; } __packed; + +#define BTP_CCP_EV_CHRC_HANDLES 0x82 +struct btp_ccp_chrc_handles_ev { + uint16_t provider_name; + uint16_t bearer_uci; + uint16_t bearer_technology; + uint16_t uri_list; + uint16_t signal_strength; + uint16_t signal_interval; + uint16_t current_calls; + uint16_t ccid; + uint16_t status_flags; + uint16_t bearer_uri; + uint16_t call_state; + uint16_t control_point; + uint16_t optional_opcodes; + uint16_t termination_reason; + uint16_t incoming_call; + uint16_t friendly_name; +}; + +#define BTP_CCP_EV_CHRC_VAL 0x83 +struct btp_ccp_chrc_val_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t inst_index; + uint8_t value; +}; + +#define BTP_CCP_EV_CHRC_STR 0x84 +struct btp_ccp_chrc_str_ev { + bt_addr_le_t address; + uint8_t status; + uint8_t inst_index; + uint8_t data_len; + char data[0]; +} __packed; + +#define BTP_CCP_EV_CP 0x85 +struct btp_ccp_cp_ev { + bt_addr_le_t address; + uint8_t status; +} __packed; + +#define BTP_CCP_EV_CURRENT_CALLS 0x86 +struct btp_ccp_current_calls_ev { + bt_addr_le_t address; + uint8_t status; +} __packed; diff --git a/tests/bluetooth/tester/src/btp_ccp.c b/tests/bluetooth/tester/src/btp_ccp.c index 6c0d18258c3a1b6..aad1431a883b199 100644 --- a/tests/bluetooth/tester/src/btp_ccp.c +++ b/tests/bluetooth/tester/src/btp_ccp.c @@ -9,10 +9,17 @@ #include "zephyr/sys/byteorder.h" #include +#include <../../subsys/bluetooth/audio/tbs_internal.h> + #include #define LOG_MODULE_NAME bttester_ccp LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); +struct btp_ccp_chrc_handles_ev tbs_handles; +struct bt_tbs_instance *tbs_inst; +static uint8_t inst_ccid; +static bool send_ev; + static uint8_t ccp_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { @@ -25,6 +32,29 @@ static uint8_t ccp_supported_commands(const void *cmd, uint16_t cmd_len, tester_set_bit(rp->data, BTP_CCP_TERMINATE_CALL); tester_set_bit(rp->data, BTP_CCP_ORIGINATE_CALL); tester_set_bit(rp->data, BTP_CCP_READ_CALL_STATE); + tester_set_bit(rp->data, BTP_CCP_READ_BEARER_NAME); + + /* octet 1 */ + tester_set_bit(rp->data, BTP_CCP_READ_BEARER_UCI); + tester_set_bit(rp->data, BTP_CCP_READ_BEARER_TECH); + tester_set_bit(rp->data, BTP_CCP_READ_URI_LIST); + tester_set_bit(rp->data, BTP_CCP_READ_SIGNAL_STRENGTH); + tester_set_bit(rp->data, BTP_CCP_READ_SIGNAL_INTERVAL); + tester_set_bit(rp->data, BTP_CCP_READ_CURRENT_CALLS); + tester_set_bit(rp->data, BTP_CCP_READ_CCID); + + /* octet 2 */ + tester_set_bit(rp->data, BTP_CCP_READ_CALL_URI); + tester_set_bit(rp->data, BTP_CCP_READ_STATUS_FLAGS); + tester_set_bit(rp->data, BTP_CCP_READ_OPTIONAL_OPCODES); + tester_set_bit(rp->data, BTP_CCP_READ_FRIENDLY_NAME); + tester_set_bit(rp->data, BTP_CCP_READ_REMOTE_URI); + tester_set_bit(rp->data, BTP_CCP_SET_SIGNAL_INTERVAL); + tester_set_bit(rp->data, BTP_CCP_HOLD_CALL); + + /* octet 3 */ + tester_set_bit(rp->data, BTP_CCP_RETRIEVE_CALL); + tester_set_bit(rp->data, BTP_CCP_JOIN_CALLS); *rsp_len = sizeof(*rp) + 1; @@ -42,96 +72,100 @@ static void tbs_client_discovered_ev(int err, uint8_t tbs_count, bool gtbs_found tester_event(BTP_SERVICE_ID_CCP, BTP_CCP_EV_DISCOVERED, &ev, sizeof(ev)); } -/** - * @brief Callback function for ccp_discover. - * - * @param conn The connection that was used to discover CCP for a - * device. - * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, - * GATT error or errno value. - * @param tbs_count Number of TBS instances on peer device. - * @param gtbs_found Whether or not the server has a Generic TBS instance. - */ -static void tbs_client_discover_cb(struct bt_conn *conn, - int err, - uint8_t tbs_count, - bool gtbs_found) +static void tbs_chrc_handles_ev(struct btp_ccp_chrc_handles_ev *tbs_handles) { - LOG_DBG("Discovered TBS - err (%u) GTBS (%u)", err, gtbs_found); + struct btp_ccp_chrc_handles_ev ev; + + ev.provider_name = sys_cpu_to_le16(tbs_handles->provider_name); + ev.bearer_uci = sys_cpu_to_le16(tbs_handles->bearer_uci); + ev.bearer_technology = sys_cpu_to_le16(tbs_handles->bearer_technology); + ev.uri_list = sys_cpu_to_le16(tbs_handles->uri_list); + ev.signal_strength = sys_cpu_to_le16(tbs_handles->signal_strength); + ev.signal_interval = sys_cpu_to_le16(tbs_handles->signal_interval); + ev.current_calls = sys_cpu_to_le16(tbs_handles->current_calls); + ev.ccid = sys_cpu_to_le16(tbs_handles->ccid); + ev.status_flags = sys_cpu_to_le16(tbs_handles->status_flags); + ev.bearer_uri = sys_cpu_to_le16(tbs_handles->bearer_uri); + ev.call_state = sys_cpu_to_le16(tbs_handles->call_state); + ev.control_point = sys_cpu_to_le16(tbs_handles->control_point); + ev.optional_opcodes = sys_cpu_to_le16(tbs_handles->optional_opcodes); + ev.termination_reason = sys_cpu_to_le16(tbs_handles->termination_reason); + ev.incoming_call = sys_cpu_to_le16(tbs_handles->incoming_call); + ev.friendly_name = sys_cpu_to_le16(tbs_handles->friendly_name); + + tester_event(BTP_SERVICE_ID_CCP, BTP_CCP_EV_CHRC_HANDLES, &ev, sizeof(ev)); +} - tbs_client_discovered_ev(err, tbs_count, gtbs_found); +static void tbs_client_chrc_val_ev(struct bt_conn *conn, uint8_t status, uint8_t inst_index, + uint32_t value) +{ + struct btp_ccp_chrc_val_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + ev.inst_index = inst_index; + ev.value = value; + + tester_event(BTP_SERVICE_ID_CCP, BTP_CCP_EV_CHRC_VAL, &ev, sizeof(ev)); } -/** - * @brief Callback function for the CCP call control functions. - * - * @param conn The connection used in the function. - * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, - * GATT error or errno value. - * @param inst_index The index of the TBS instance that was updated. - * @param call_index The call index. For #bt_tbs_client_originate_call this will - * always be 0, and does not reflect the actual call index. - */ -static void tbs_client_originate_call_cb(struct bt_conn *conn, - int err, - uint8_t inst_index, - uint8_t call_index) +static void tbs_client_chrc_str_ev(struct bt_conn *conn, uint8_t status, uint8_t inst_index, + uint8_t data_len, const char *data) { - LOG_DBG("Originate call - err (%u) Call Index (%u)", err, call_index); + struct btp_ccp_chrc_str_ev *ev; + + tester_rsp_buffer_lock(); + tester_rsp_buffer_allocate(sizeof(*ev) + data_len, (uint8_t **)&ev); + bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn)); + ev->status = status; + ev->inst_index = inst_index; + ev->data_len = data_len; + memcpy(ev->data, data, data_len); + + tester_event(BTP_SERVICE_ID_CCP, BTP_CCP_EV_CHRC_STR, ev, sizeof(*ev) + data_len); + + tester_rsp_buffer_free(); + tester_rsp_buffer_unlock(); } -/** - * @brief Callback function for the CCP call control functions. - * - * @param conn The connection used in the function. - * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, - * GATT error or errno value. - * @param inst_index The index of the TBS instance that was updated. - * @param call_index The call index. For #bt_tbs_client_originate_call this will - * always be 0, and does not reflect the actual call index. - */ -static void tbs_client_terminate_call_cb(struct bt_conn *conn, - int err, - uint8_t inst_index, - uint8_t call_index) +static void tbs_client_cp_ev(struct bt_conn *conn, uint8_t status) { - LOG_DBG("Terminate call - err (%u) Call Index (%u)", err, call_index); + struct btp_ccp_cp_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + + tester_event(BTP_SERVICE_ID_CCP, BTP_CCP_EV_CP, &ev, sizeof(ev)); } -/** - * @brief Callback function for the CCP call control functions. - * - * @param conn The connection used in the function. - * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, - * GATT error or errno value. - * @param inst_index The index of the TBS instance that was updated. - * @param call_index The call index. For #bt_tbs_client_originate_call this will - * always be 0, and does not reflect the actual call index. - */ -static void tbs_client_accept_call_cb(struct bt_conn *conn, - int err, - uint8_t inst_index, - uint8_t call_index) +static void tbs_client_current_calls_ev(struct bt_conn *conn, uint8_t status) { - LOG_DBG("Accept call - err (%u) Call Index (%u)", err, call_index); + struct btp_ccp_current_calls_ev ev; + + bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn)); + + ev.status = status; + + tester_event(BTP_SERVICE_ID_CCP, BTP_CCP_EV_CURRENT_CALLS, &ev, sizeof(ev)); } -/** - * @brief Callback function for the CCP call control functions. - * - * @param conn The connection used in the function. - * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, - * GATT error or errno value. - * @param inst_index The index of the TBS instance that was updated. - * @param call_index The call index. For #bt_tbs_client_originate_call this will - * always be 0, and does not reflect the actual call index. - */ -static void tbs_client_retrieve_call_cb(struct bt_conn *conn, - int err, - uint8_t inst_index, - uint8_t call_index) +static void tbs_client_discover_cb(struct bt_conn *conn, int err, uint8_t tbs_count, + bool gtbs_found) { - LOG_DBG("Retrieve call - err (%u) Call Index (%u)", err, call_index); + if (err) { + LOG_DBG("Discovery Failed (%d)", err); + return; + } + + LOG_DBG("Discovered TBS - err (%u) GTBS (%u)", err, gtbs_found); + + bt_tbs_client_read_ccid(conn, 0xFF); + + tbs_client_discovered_ev(err, tbs_count, gtbs_found); + + send_ev = true; } typedef struct bt_tbs_client_call_state bt_tbs_client_call_state_t; @@ -160,17 +194,6 @@ static void tbs_client_call_states_ev(int err, tester_event(BTP_SERVICE_ID_CCP, BTP_CCP_EV_CALL_STATES, buf->data, buf->len); } -/** - * @brief Callback function for ccp_read_call_state. - * - * @param conn The connection used in the function. - * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, - * GATT error or errno value. - * @param inst_index The index of the TBS instance that was updated. - * @param call_count Number of call states read. - * @param call_states Array of call states. The array is not kept by - * the client, so must be copied to be saved. - */ static void tbs_client_call_states_cb(struct bt_conn *conn, int err, uint8_t inst_index, @@ -182,16 +205,6 @@ static void tbs_client_call_states_cb(struct bt_conn *conn, tbs_client_call_states_ev(err, inst_index, call_count, call_states); } -/** - * @brief Callback function for ccp_read_termination_reason. - * - * @param conn The connection used in the function. - * @param err Error value. BT_TBS_CLIENT_RESULT_CODE_*, - * GATT error or errno value. - * @param inst_index The index of the TBS instance that was updated. - * @param call_index The call index. - * @param reason The termination reason. - */ static void tbs_client_termination_reason_cb(struct bt_conn *conn, int err, uint8_t inst_index, @@ -202,14 +215,90 @@ static void tbs_client_termination_reason_cb(struct bt_conn *conn, err, call_index, reason); } +static void tbs_client_read_string_cb(struct bt_conn *conn, int err, uint8_t inst_index, + const char *value) +{ + LOG_DBG("TBS Client read string characteristic value cb"); + + uint8_t data_len = strlen(value); + + tbs_client_chrc_str_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, inst_index, + data_len, value); +} + +static void tbs_client_read_val_cb(struct bt_conn *conn, int err, uint8_t inst_index, + uint32_t value) +{ + LOG_DBG("TBS Client read characteristic value cb"); + + tbs_client_chrc_val_ev(conn, err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS, inst_index, + value); + + if (send_ev == true) { + inst_ccid = value; + + tbs_inst = bt_tbs_client_get_by_ccid(conn, inst_ccid); + + tbs_handles.provider_name = tbs_inst->name_sub_params.value_handle; + tbs_handles.bearer_uci = tbs_inst->bearer_uci_handle; + tbs_handles.bearer_technology = tbs_inst->technology_sub_params.value_handle; + tbs_handles.uri_list = tbs_inst->uri_list_handle; + tbs_handles.signal_strength = tbs_inst->signal_strength_sub_params.value_handle; + tbs_handles.signal_interval = tbs_inst->signal_interval_handle; + tbs_handles.current_calls = tbs_inst->current_calls_sub_params.value_handle; + tbs_handles.ccid = tbs_inst->ccid_handle; + tbs_handles.status_flags = tbs_inst->status_flags_sub_params.value_handle; + tbs_handles.bearer_uri = tbs_inst->in_target_uri_sub_params.value_handle; + tbs_handles.call_state = tbs_inst->call_state_sub_params.value_handle; + tbs_handles.control_point = tbs_inst->call_cp_sub_params.value_handle; + tbs_handles.optional_opcodes = tbs_inst->optional_opcodes_handle; + tbs_handles.termination_reason = tbs_inst->termination_reason_handle; + tbs_handles.incoming_call = tbs_inst->incoming_call_sub_params.value_handle; + tbs_handles.friendly_name = tbs_inst->friendly_name_sub_params.value_handle; + + tbs_chrc_handles_ev(&tbs_handles); + send_ev = false; + } +} + +static void tbs_client_current_calls_cb(struct bt_conn *conn, int err, uint8_t inst_index, + uint8_t call_count, const struct bt_tbs_client_call *calls) +{ + LOG_DBG(""); + + tbs_client_current_calls_ev(conn, err); +} + +static void tbs_client_cp_cb(struct bt_conn *conn, int err, uint8_t inst_index, uint8_t call_index) +{ + LOG_DBG(""); + + tbs_client_cp_ev(conn, err); +} + static const struct bt_tbs_client_cb tbs_client_callbacks = { .discover = tbs_client_discover_cb, - .originate_call = tbs_client_originate_call_cb, - .terminate_call = tbs_client_terminate_call_cb, - .accept_call = tbs_client_accept_call_cb, - .retrieve_call = tbs_client_retrieve_call_cb, + .originate_call = tbs_client_cp_cb, + .terminate_call = tbs_client_cp_cb, .call_state = tbs_client_call_states_cb, - .termination_reason = tbs_client_termination_reason_cb + .termination_reason = tbs_client_termination_reason_cb, + .bearer_provider_name = tbs_client_read_string_cb, + .bearer_uci = tbs_client_read_string_cb, + .technology = tbs_client_read_val_cb, + .uri_list = tbs_client_read_string_cb, + .signal_strength = tbs_client_read_val_cb, + .signal_interval = tbs_client_read_val_cb, + .current_calls = tbs_client_current_calls_cb, + .ccid = tbs_client_read_val_cb, + .call_uri = tbs_client_read_string_cb, + .status_flags = tbs_client_read_val_cb, + .optional_opcodes = tbs_client_read_val_cb, + .friendly_name = tbs_client_read_string_cb, + .remote_uri = tbs_client_read_string_cb, + .accept_call = tbs_client_cp_cb, + .hold_call = tbs_client_cp_cb, + .retrieve_call = tbs_client_cp_cb, + .join_calls = tbs_client_cp_cb, }; static uint8_t ccp_discover_tbs(const void *cmd, uint16_t cmd_len, @@ -293,6 +382,362 @@ static uint8_t ccp_read_call_state(const void *cmd, uint16_t cmd_len, return BTP_STATUS_VAL(err); } +static uint8_t ccp_read_bearer_name(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_bearer_name_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_bearer_provider_name(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_bearer_uci(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_bearer_uci_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_bearer_uci(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_bearer_tech(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_bearer_technology_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_technology(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_uri_list(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_ccp_read_uri_list_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_uri_list(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_signal_strength(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_signal_strength_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_signal_strength(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_signal_interval(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_signal_interval_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_signal_interval(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_current_calls(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_current_calls_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_current_calls(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_ccid(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_ccid_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_ccid(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_call_uri(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_call_uri_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_call_uri(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_status_flags(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_status_flags_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_status_flags(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_optional_opcodes(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_optional_opcodes_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_optional_opcodes(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_friendly_name(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_friendly_name_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_friendly_name(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_read_remote_uri(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_read_remote_uri_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_read_remote_uri(conn, cp->inst_index); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_set_signal_interval(const void *cmd, uint16_t cmd_len, void *rsp, + uint16_t *rsp_len) +{ + const struct btp_ccp_set_signal_interval_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_set_signal_strength_interval(conn, cp->inst_index, cp->interval); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_hold_call(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_ccp_hold_call_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_hold_call(conn, cp->inst_index, cp->call_id); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_retrieve_call(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_ccp_retrieve_call_cmd *cp = cmd; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + err = bt_tbs_client_retrieve_call(conn, cp->inst_index, cp->call_id); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + +static uint8_t ccp_join_calls(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_ccp_join_calls_cmd *cp = cmd; + const uint8_t *call_index; + struct bt_conn *conn; + int err; + + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address); + if (!conn) { + LOG_ERR("Unknown connection"); + return BTP_STATUS_FAILED; + } + + call_index = cp->call_index; + + err = bt_tbs_client_join_calls(conn, cp->inst_index, call_index, cp->count); + if (err) { + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + static const struct btp_handler ccp_handlers[] = { { .opcode = BTP_CCP_READ_SUPPORTED_COMMANDS, @@ -324,7 +769,92 @@ static const struct btp_handler ccp_handlers[] = { .opcode = BTP_CCP_READ_CALL_STATE, .expect_len = sizeof(struct btp_ccp_read_call_state_cmd), .func = ccp_read_call_state - } + }, + { + .opcode = BTP_CCP_READ_BEARER_NAME, + .expect_len = sizeof(struct btp_ccp_read_bearer_name_cmd), + .func = ccp_read_bearer_name + }, + { + .opcode = BTP_CCP_READ_BEARER_UCI, + .expect_len = sizeof(struct btp_ccp_read_bearer_uci_cmd), + .func = ccp_read_bearer_uci + }, + { + .opcode = BTP_CCP_READ_BEARER_TECH, + .expect_len = sizeof(struct btp_ccp_read_bearer_technology_cmd), + .func = ccp_read_bearer_tech + }, + { + .opcode = BTP_CCP_READ_URI_LIST, + .expect_len = sizeof(struct btp_ccp_read_uri_list_cmd), + .func = ccp_read_uri_list + }, + { + .opcode = BTP_CCP_READ_SIGNAL_STRENGTH, + .expect_len = sizeof(struct btp_ccp_read_signal_strength_cmd), + .func = ccp_read_signal_strength + }, + { + .opcode = BTP_CCP_READ_SIGNAL_INTERVAL, + .expect_len = sizeof(struct btp_ccp_read_signal_interval_cmd), + .func = ccp_read_signal_interval + }, + { + .opcode = BTP_CCP_READ_CURRENT_CALLS, + .expect_len = sizeof(struct btp_ccp_read_current_calls_cmd), + .func = ccp_read_current_calls + }, + { + .opcode = BTP_CCP_READ_CCID, + .expect_len = sizeof(struct btp_ccp_read_ccid_cmd), + .func = ccp_read_ccid + }, + { + .opcode = BTP_CCP_READ_CALL_URI, + .expect_len = sizeof(struct btp_ccp_read_call_uri_cmd), + .func = ccp_read_call_uri + }, + { + .opcode = BTP_CCP_READ_STATUS_FLAGS, + .expect_len = sizeof(struct btp_ccp_read_status_flags_cmd), + .func = ccp_read_status_flags + }, + { + .opcode = BTP_CCP_READ_OPTIONAL_OPCODES, + .expect_len = sizeof(struct btp_ccp_read_optional_opcodes_cmd), + .func = ccp_read_optional_opcodes + }, + { + .opcode = BTP_CCP_READ_FRIENDLY_NAME, + .expect_len = sizeof(struct btp_ccp_read_friendly_name_cmd), + .func = ccp_read_friendly_name + }, + { + .opcode = BTP_CCP_READ_REMOTE_URI, + .expect_len = sizeof(struct btp_ccp_read_remote_uri_cmd), + .func = ccp_read_remote_uri + }, + { + .opcode = BTP_CCP_SET_SIGNAL_INTERVAL, + .expect_len = sizeof(struct btp_ccp_set_signal_interval_cmd), + .func = ccp_set_signal_interval + }, + { + .opcode = BTP_CCP_HOLD_CALL, + .expect_len = sizeof(struct btp_ccp_hold_call_cmd), + .func = ccp_hold_call + }, + { + .opcode = BTP_CCP_RETRIEVE_CALL, + .expect_len = sizeof(struct btp_ccp_retrieve_call_cmd), + .func = ccp_retrieve_call + }, + { + .opcode = BTP_CCP_JOIN_CALLS, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = ccp_join_calls + }, }; uint8_t tester_init_ccp(void) diff --git a/tests/bsim/bluetooth/audio/prj.conf b/tests/bsim/bluetooth/audio/prj.conf index 06114766881440f..e3510c63b181d91 100644 --- a/tests/bsim/bluetooth/audio/prj.conf +++ b/tests/bsim/bluetooth/audio/prj.conf @@ -30,10 +30,10 @@ CONFIG_BT_BAP_BROADCAST_SOURCE=y CONFIG_BT_BAP_BROADCAST_SINK=y CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE=196 CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE=196 -CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=1 +CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=2 CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=1 CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT=1 -CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT=1 +CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT=2 CONFIG_BT_ISO_TX_BUF_COUNT=4 CONFIG_BT_ISO_MAX_CHAN=4 CONFIG_BT_ISO_TX_MTU=310 @@ -149,6 +149,9 @@ CONFIG_BT_GATT_AUTO_RESUBSCRIBE=n # Gaming Audio Profile CONFIG_BT_GMAP=y +# Public Broadcast Profile +CONFIG_BT_PBP=y + # DEBUGGING CONFIG_LOG=y CONFIG_LOG_FUNC_NAME_PREFIX_ERR=y @@ -200,8 +203,9 @@ CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 # Controller ISO Broadcast Settings -CONFIG_BT_CTLR_ADV_ISO_STREAM_COUNT=1 -CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=1 +CONFIG_BT_CTLR_ADV_ISO_STREAM_COUNT=2 +CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 +CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 # Controller ISO Unicast Settings CONFIG_BT_CTLR_CENTRAL_ISO=y diff --git a/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c b/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c index 5410d76defaffb4..1559f8c30108d1c 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_source_test.c @@ -121,7 +121,7 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source) } for (size_t i = 0U; i < ARRAY_SIZE(subgroup_params); i++) { - subgroup_params[i].params_count = 1U; + subgroup_params[i].params_count = ARRAY_SIZE(stream_params); subgroup_params[i].params = &stream_params[i]; subgroup_params[i].codec_cfg = &preset_16_1_1.codec_cfg; } @@ -178,6 +178,8 @@ static int setup_extended_adv(struct bt_bap_broadcast_source *source, struct bt_ /* Broadcast Audio Streaming Endpoint advertising data */ NET_BUF_SIMPLE_DEFINE(ad_buf, BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); + struct bt_le_adv_param adv_param = BT_LE_ADV_PARAM_INIT( + BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_USE_NAME, 0x80, 0x80, NULL); NET_BUF_SIMPLE_DEFINE(base_buf, 128); struct bt_data ext_ad; struct bt_data per_ad; @@ -185,7 +187,7 @@ static int setup_extended_adv(struct bt_bap_broadcast_source *source, struct bt_ int err; /* Create a non-connectable non-scannable advertising set */ - err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN_NAME, NULL, adv); + err = bt_le_ext_adv_create(&adv_param, NULL, adv); if (err != 0) { printk("Unable to create extended advertising set: %d\n", err); return err; diff --git a/tests/bsim/bluetooth/audio/src/common.h b/tests/bsim/bluetooth/audio/src/common.h index 0fb3aac451d40a8..2e87bac169e5503 100644 --- a/tests/bsim/bluetooth/audio/src/common.h +++ b/tests/bsim/bluetooth/audio/src/common.h @@ -87,6 +87,8 @@ static const uint8_t mock_iso_data[] = { #define SYNC_RETRY_COUNT 6 /* similar to retries for connections */ #define PA_SYNC_SKIP 5 +#define PBP_STREAMS_TO_SEND 2 + extern struct bt_le_scan_cb common_scan_cb; extern const struct bt_data ad[AD_SIZE]; extern struct bt_conn *default_conn; diff --git a/tests/bsim/bluetooth/audio/src/main.c b/tests/bsim/bluetooth/audio/src/main.c index 284f29ca88f7800..50784a4dc4d619f 100644 --- a/tests/bsim/bluetooth/audio/src/main.c +++ b/tests/bsim/bluetooth/audio/src/main.c @@ -36,6 +36,8 @@ extern struct bst_test_list *test_tmap_client_install(struct bst_test_list *test extern struct bst_test_list *test_tmap_server_install(struct bst_test_list *tests); extern struct bst_test_list *test_pacs_notify_client_install(struct bst_test_list *tests); extern struct bst_test_list *test_pacs_notify_server_install(struct bst_test_list *tests); +extern struct bst_test_list *test_public_broadcast_source_install(struct bst_test_list *tests); +extern struct bst_test_list *test_public_broadcast_sink_install(struct bst_test_list *tests); extern struct bst_test_list *test_csip_notify_client_install(struct bst_test_list *tests); extern struct bst_test_list *test_csip_notify_server_install(struct bst_test_list *tests); extern struct bst_test_list *test_gmap_ugg_install(struct bst_test_list *tests); @@ -72,6 +74,8 @@ bst_test_install_t test_installers[] = { test_tmap_client_install, test_pacs_notify_client_install, test_pacs_notify_server_install, + test_public_broadcast_source_install, + test_public_broadcast_sink_install, test_csip_notify_client_install, test_csip_notify_server_install, test_gmap_ugg_install, diff --git a/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c new file mode 100644 index 000000000000000..6154fae570ebff0 --- /dev/null +++ b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_sink_test.c @@ -0,0 +1,432 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if defined(CONFIG_BT_PBP) + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +#define SEM_TIMEOUT K_SECONDS(1.5) +#define PA_SYNC_SKIP 5 +#define SYNC_RETRY_COUNT 6 /* similar to retries for connections */ + +extern enum bst_result_t bst_result; + +static bool pbs_found; + +static K_SEM_DEFINE(sem_pa_synced, 0U, 1U); +static K_SEM_DEFINE(sem_base_received, 0U, 1U); +static K_SEM_DEFINE(sem_syncable, 0U, 1U); +static K_SEM_DEFINE(sem_pa_sync_lost, 0U, 1U); +static K_SEM_DEFINE(sem_data_received, 0U, 1U); + +static struct bt_bap_broadcast_sink *broadcast_sink; +static struct bt_le_per_adv_sync *bcast_pa_sync; + +static struct bt_bap_stream streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; +static struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)]; + +static const struct bt_audio_codec_cap codec = + BT_AUDIO_CODEC_CAP_LC3(BT_AUDIO_CODEC_LC3_FREQ_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_24KHZ + | BT_AUDIO_CODEC_LC3_FREQ_48KHZ, + BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 155u, 1u, + BT_AUDIO_CONTEXT_TYPE_MEDIA +); + +/* Create a mask for the maximum BIS we can sync to using the number of streams + * we have. We add an additional 1 since the bis indexes start from 1 and not + * 0. + */ +static const uint32_t bis_index_mask = BIT_MASK(ARRAY_SIZE(streams) + 1U); +static uint32_t bis_index_bitfield; +static uint32_t broadcast_id = INVALID_BROADCAST_ID; + +static struct bt_pacs_cap cap = { + .codec_cap = &codec, +}; + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, + struct net_buf_simple *ad); + +static struct bt_le_scan_cb broadcast_scan_cb = { + .recv = broadcast_scan_recv +}; + +static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base, + size_t base_size) +{ + k_sem_give(&sem_base_received); +} + +static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted) +{ + k_sem_give(&sem_syncable); +} + +static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = { + .base_recv = base_recv_cb, + .syncable = syncable_cb, +}; + +static void started_cb(struct bt_bap_stream *stream) +{ + printk("Stream %p started\n", stream); +} + +static void stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + printk("Stream %p stopped with reason 0x%02X\n", stream, reason); +} + +static void recv_cb(struct bt_bap_stream *stream, + const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + static uint32_t recv_cnt; + + recv_cnt++; + if (recv_cnt >= MIN_SEND_COUNT) { + k_sem_give(&sem_data_received); + } + printk("Receiving ISO packets\n"); +} + +static uint16_t interval_to_sync_timeout(uint16_t interval) +{ + uint32_t interval_ms; + uint16_t timeout; + + /* Ensure that the following calculation does not overflow silently */ + __ASSERT(SYNC_RETRY_COUNT < 10, "SYNC_RETRY_COUNT shall be less than 10"); + + /* Add retries and convert to unit in 10's of ms */ + interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(interval); + timeout = (interval_ms * SYNC_RETRY_COUNT) / 10; + + /* Enforce restraints */ + timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, + BT_GAP_PER_ADV_MAX_TIMEOUT); + + return timeout; +} + +static bool pa_decode_base(struct bt_data *data, void *user_data) +{ + const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); + uint32_t base_bis_index_bitfield = 0U; + int err; + + /* Base is NULL if the data does not contain a valid BASE */ + if (base == NULL) { + return true; + } + + err = bt_bap_base_get_bis_indexes(base, &base_bis_index_bitfield); + if (err != 0) { + return false; + } + + bis_index_bitfield = base_bis_index_bitfield & bis_index_mask; + k_sem_give(&sem_base_received); + + return false; +} + +static void broadcast_pa_recv(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_recv_info *info, + struct net_buf_simple *buf) +{ + bt_data_parse(buf, pa_decode_base, NULL); +} + +static void broadcast_pa_synced(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info) +{ + k_sem_give(&sem_pa_synced); +} + +static void broadcast_pa_terminated(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_term_info *info) +{ + if (sync == bcast_pa_sync) { + printk("PA sync %p lost with reason %u\n", sync, info->reason); + bcast_pa_sync = NULL; + + k_sem_give(&sem_pa_sync_lost); + } +} + +static struct bt_bap_stream_ops stream_ops = { + .started = started_cb, + .stopped = stopped_cb, + .recv = recv_cb +}; + +static struct bt_le_per_adv_sync_cb broadcast_sync_cb = { + .synced = broadcast_pa_synced, + .recv = broadcast_pa_recv, + .term = broadcast_pa_terminated, +}; + +static int reset(void) +{ + int err; + + k_sem_reset(&sem_pa_synced); + k_sem_reset(&sem_base_received); + k_sem_reset(&sem_syncable); + k_sem_reset(&sem_pa_sync_lost); + + if (broadcast_sink != NULL) { + err = bt_bap_broadcast_sink_delete(broadcast_sink); + if (err) { + printk("Deleting broadcast sink failed (err %d)\n", err); + + return err; + } + + broadcast_sink = NULL; + } + + return 0; +} + +static int init(void) +{ + int err; + + err = bt_enable(NULL); + if (err) { + FAIL("Bluetooth enable failed (err %d)\n", err); + + return err; + } + + printk("Bluetooth initialized\n"); + + bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs); + bt_le_per_adv_sync_cb_register(&broadcast_sync_cb); + + err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); + if (err) { + printk("Capability register failed (err %d)\n", err); + + return err; + } + + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + streams[i].ops = &stream_ops; + } + + for (size_t i = 0U; i < ARRAY_SIZE(streams_p); i++) { + streams_p[i] = &streams[i]; + } + + return 0; +} + +static void sync_broadcast_pa(const struct bt_le_scan_recv_info *info) +{ + struct bt_le_per_adv_sync_param param; + int err; + + /* Unregister the callbacks to prevent broadcast_scan_recv to be called again */ + bt_le_scan_cb_unregister(&broadcast_scan_cb); + err = bt_le_scan_stop(); + if (err != 0) { + printk("Could not stop scan: %d", err); + } + + bt_addr_le_copy(¶m.addr, info->addr); + param.options = 0; + param.sid = info->sid; + param.skip = PA_SYNC_SKIP; + param.timeout = interval_to_sync_timeout(info->interval); + err = bt_le_per_adv_sync_create(¶m, &bcast_pa_sync); + if (err != 0) { + printk("Could not sync to PA: %d", err); + + } +} + +static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) +{ + struct bt_uuid_16 adv_uuid; + uint8_t source_features = 0U; + uint8_t meta[50]; + + if (data->type != BT_DATA_SVC_DATA16) { + return true; + } + + if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + return true; + } + + if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) { + /* Save broadcast_id */ + if (broadcast_id == INVALID_BROADCAST_ID) { + broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); + } + + /* Found Broadcast Audio and Public Broadcast Announcement Services */ + if (pbs_found) { + return false; + } + } + + if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_PBA)) { + bt_pbp_parse_announcement(data, &source_features, meta); + if (!(source_features & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY)) { + /* This is a Standard Quality Public Broadcast Audio stream - do not sync */ + printk("This is a Standard Quality Public Broadcast Audio stream\n"); + pbs_found = false; + + return true; + } + + printk("Found Suitable Public Broadcast Announcement\n"); + pbs_found = true; + + /* Continue parsing if Broadcast Audio Announcement Service was not found */ + if (broadcast_id == INVALID_BROADCAST_ID) { + return true; + } + + return false; + } + + /* Continue parsing */ + return true; +} + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, + struct net_buf_simple *ad) +{ + pbs_found = false; + + /* We are only interested in non-connectable periodic advertisers */ + if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) || + info->interval == 0) { + return; + } + + bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)&broadcast_id); + + if ((broadcast_id != INVALID_BROADCAST_ID) && pbs_found) { + sync_broadcast_pa(info); + } +} + +static void test_main(void) +{ + int count = 0; + int err; + + init(); + + while (count < PBP_STREAMS_TO_SEND) { + err = reset(); + if (err != 0) { + printk("Resetting failed: %d\n", err); + break; + } + + /* Register callbacks */ + bt_le_scan_cb_register(&broadcast_scan_cb); + + /* Start scanning */ + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err) { + printk("Scan start failed (err %d)\n", err); + break; + } + + /* Wait for PA sync */ + err = k_sem_take(&sem_pa_synced, SEM_TIMEOUT); + if (err != 0) { + printk("sem_pa_synced timed out\n"); + break; + } + + /* Wait for BASE decode */ + err = k_sem_take(&sem_base_received, SEM_TIMEOUT); + if (err != 0) { + printk("sem_base_received timed out\n"); + break; + } + + /* Create broadcast sink */ + err = bt_bap_broadcast_sink_create(bcast_pa_sync, broadcast_id, &broadcast_sink); + if (err != 0) { + printk("Sink not created!\n"); + break; + } + + k_sem_take(&sem_syncable, SEM_TIMEOUT); + if (err != 0) { + printk("sem_syncable timed out\n"); + break; + } + + /* Sync to broadcast source */ + err = bt_bap_broadcast_sink_sync(broadcast_sink, bis_index_bitfield, + streams_p, NULL); + if (err != 0) { + printk("Unable to sync to broadcast source: %d\n", err); + break; + } + + /* Wait for data */ + k_sem_take(&sem_data_received, SEM_TIMEOUT); + + /* Wait for the stream to end */ + k_sem_take(&sem_pa_sync_lost, SEM_TIMEOUT); + + count++; + } + + if (count == PBP_STREAMS_TO_SEND - 1) { + /* Pass if we synced only with the high quality broadcast */ + PASS("Public Broadcast sink passed\n"); + } else { + FAIL("Public Broadcast sink failed\n"); + } +} + +static const struct bst_test_instance test_public_broadcast_sink[] = { + { + .test_id = "public_broadcast_sink", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main + }, + BSTEST_END_MARKER +}; + +struct bst_test_list *test_public_broadcast_sink_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_public_broadcast_sink); +} + +#else /* !CONFIG_BT_PBP */ + +struct bst_test_list *test_public_broadcast_sink_install(struct bst_test_list *tests) +{ + return tests; +} + +#endif /* CONFIG_BT_PBP */ diff --git a/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_source_test.c b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_source_test.c new file mode 100644 index 000000000000000..4602e4963b276be --- /dev/null +++ b/tests/bsim/bluetooth/audio/src/pbp_public_broadcast_source_test.c @@ -0,0 +1,394 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if defined(CONFIG_BT_PBP) + +#include +#include +#include +#include +#include +#include + +#include "common.h" + +/* When BROADCAST_ENQUEUE_COUNT > 1 we can enqueue enough buffers to ensure that + * the controller is never idle + */ +#define BROADCAST_ENQUEUE_COUNT 2U +#define BUF_NEEDED (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT) +/* PBS ASCII text */ +#define PBS_DEMO 'P', 'B', 'P' +#define SEM_TIMEOUT K_SECONDS(2) + +extern enum bst_result_t bst_result; + +BUILD_ASSERT(CONFIG_BT_ISO_TX_BUF_COUNT >= BUF_NEEDED, + "CONFIG_BT_ISO_TX_BUF_COUNT should be at least " + "BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT"); + +NET_BUF_POOL_FIXED_DEFINE(tx_pool, + BUF_NEEDED, + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +const uint8_t pba_metadata[] = { + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, PBS_DEMO)}; + +static uint8_t bis_codec_data[] = { + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_FREQ, + BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ))}; + +static struct bt_cap_stream broadcast_source_stream; +static struct bt_cap_stream *broadcast_stream; + +static struct bt_cap_initiator_broadcast_stream_param stream_params; +static struct bt_cap_initiator_broadcast_subgroup_param subgroup_param; +static struct bt_cap_initiator_broadcast_create_param create_param; +static struct bt_cap_broadcast_source *broadcast_source; + +static struct bt_bap_lc3_preset broadcast_preset_48_2_1 = + BT_BAP_LC3_UNICAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT, + BT_AUDIO_CONTEXT_TYPE_MEDIA); + +static K_SEM_DEFINE(sem_started, 0U, 1); +static K_SEM_DEFINE(sem_stopped, 0U, 1); + +struct bt_le_ext_adv *adv; + +static void started_cb(struct bt_bap_stream *stream) +{ + printk("Stream %p started\n", stream); + k_sem_give(&sem_started); +} + +static void stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + printk("Stream %p stopped with reason 0x%02X\n", stream, reason); + k_sem_give(&sem_stopped); +} + +static void sent_cb(struct bt_bap_stream *stream) +{ + static uint8_t mock_data[CONFIG_BT_ISO_TX_MTU]; + static bool mock_data_initialized; + static uint32_t seq_num; + struct net_buf *buf; + int ret; + + if (broadcast_preset_48_2_1.qos.sdu > CONFIG_BT_ISO_TX_MTU) { + printk("Invalid SDU %u for the MTU: %d", + broadcast_preset_48_2_1.qos.sdu, CONFIG_BT_ISO_TX_MTU); + return; + } + + if (!mock_data_initialized) { + for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) { + /* Initialize mock data */ + mock_data[i] = (uint8_t)i; + } + mock_data_initialized = true; + } + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + if (buf == NULL) { + printk("Could not allocate buffer when sending on %p\n", stream); + return; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + net_buf_add_mem(buf, mock_data, broadcast_preset_48_2_1.qos.sdu); + ret = bt_bap_stream_send(stream, buf, seq_num++, BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + /* This will end broadcasting on this stream. */ + net_buf_unref(buf); + return; + } +} + +static int setup_extended_adv_data(struct bt_cap_broadcast_source *source, + struct bt_le_ext_adv *adv) +{ + /* Broadcast Audio Streaming Endpoint advertising data */ + NET_BUF_SIMPLE_DEFINE(ad_buf, BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); + NET_BUF_SIMPLE_DEFINE(pbp_ad_buf, BT_UUID_SIZE_16 + 1 + ARRAY_SIZE(pba_metadata)); + NET_BUF_SIMPLE_DEFINE(base_buf, 128); + static enum bt_pbp_announcement_feature pba_params; + struct bt_data ext_ad[2]; + struct bt_data per_ad; + uint32_t broadcast_id; + int err; + + err = bt_cap_initiator_broadcast_get_id(source, &broadcast_id); + if (err != 0) { + printk("Unable to get broadcast ID: %d\n", err); + + return err; + } + + /* Broadcast Audio Announcements */ + net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); + net_buf_simple_add_le24(&ad_buf, broadcast_id); + ext_ad[0].type = BT_DATA_SVC_DATA16; + ext_ad[0].data_len = ad_buf.len + sizeof(ext_ad[0].type); + ext_ad[0].data = ad_buf.data; + + /** + * Create a Public Broadcast Announcement + * Cycle between high and standard quality public broadcast audio. + */ + if (pba_params & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY) { + pba_params = 0; + pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_STANDARD_QUALITY; + printk("Starting stream with standard quality!\n"); + } else { + pba_params = 0; + pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY; + printk("Starting stream with high quality!\n"); + } + + err = bt_pbp_get_announcement(pba_metadata, ARRAY_SIZE(pba_metadata) - 1, + pba_params, &pbp_ad_buf); + if (err != 0) { + printk("Failed to create public broadcast announcement!: %d\n", err); + + return err; + } + ext_ad[1].type = BT_DATA_SVC_DATA16; + ext_ad[1].data_len = pbp_ad_buf.len; + ext_ad[1].data = pbp_ad_buf.data; + + err = bt_le_ext_adv_set_data(adv, ext_ad, ARRAY_SIZE(ext_ad), NULL, 0); + if (err != 0) { + printk("Failed to set extended advertising data: %d\n", err); + + return err; + } + + /* Setup periodic advertising data */ + err = bt_cap_initiator_broadcast_get_base(source, &base_buf); + if (err != 0) { + printk("Failed to get encoded BASE: %d\n", err); + + return err; + } + + per_ad.type = BT_DATA_SVC_DATA16; + per_ad.data_len = base_buf.len; + per_ad.data = base_buf.data; + err = bt_le_per_adv_set_data(adv, &per_ad, 1); + if (err != 0) { + printk("Failed to set periodic advertising data: %d\n", err); + + return err; + } + + return 0; +} + +static int start_extended_adv(struct bt_le_ext_adv *adv) +{ + int err; + + /* Start extended advertising */ + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err) { + printk("Failed to start extended advertising: %d\n", err); + + return err; + } + + /* Enable Periodic Advertising */ + err = bt_le_per_adv_start(adv); + if (err) { + printk("Failed to enable periodic advertising: %d\n", err); + + return err; + } + + return 0; +} + +static int setup_extended_adv(struct bt_le_ext_adv **adv) +{ + int err; + + /* Create a non-connectable non-scannable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN_NAME, NULL, adv); + if (err != 0) { + printk("Unable to create extended advertising set: %d\n", err); + + return err; + } + + /* Set periodic advertising parameters */ + err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT); + if (err) { + printk("Failed to set periodic advertising parameters: %d\n", err); + + return err; + } + + return 0; +} + +static int stop_extended_adv(struct bt_le_ext_adv *adv) +{ + int err; + + err = bt_le_per_adv_stop(adv); + if (err) { + printk("Failed to stop periodic advertising: %d\n", err); + + return err; + } + + err = bt_le_ext_adv_stop(adv); + if (err) { + printk("Failed to stop extended advertising: %d\n", err); + + return err; + } + + err = bt_le_ext_adv_delete(adv); + if (err) { + printk("Failed to delete extended advertising: %d\n", err); + + return err; + } + + return 0; +} + +static struct bt_bap_stream_ops broadcast_stream_ops = { + .started = started_cb, + .stopped = stopped_cb, + .sent = sent_cb +}; + +static void test_main(void) +{ + int err; + int count = 0; + + err = bt_enable(NULL); + if (err) { + FAIL("Bluetooth enable failed (err %d)\n", err); + + return; + } + + broadcast_stream = &broadcast_source_stream; + bt_bap_stream_cb_register(&broadcast_stream->bap_stream, &broadcast_stream_ops); + + stream_params.stream = &broadcast_source_stream; + stream_params.data_len = ARRAY_SIZE(bis_codec_data); + stream_params.data = bis_codec_data; + + subgroup_param.stream_count = 1U; + subgroup_param.stream_params = &stream_params; + subgroup_param.codec_cfg = &broadcast_preset_48_2_1.codec_cfg; + + create_param.subgroup_count = 1U; + create_param.subgroup_params = &subgroup_param; + create_param.qos = &broadcast_preset_48_2_1.qos; + create_param.packing = BT_ISO_PACKING_SEQUENTIAL; + create_param.encryption = false; + + while (count < PBP_STREAMS_TO_SEND) { + k_sem_reset(&sem_started); + k_sem_reset(&sem_stopped); + + err = setup_extended_adv(&adv); + if (err != 0) { + printk("Unable to setup extended advertiser: %d\n", err); + FAIL("Public Broadcast source failed\n"); + } + + err = bt_cap_initiator_broadcast_audio_create(&create_param, &broadcast_source); + if (err != 0) { + printk("Unable to create broadcast source: %d\n", err); + FAIL("Public Broadcast source failed\n"); + } + + err = bt_cap_initiator_broadcast_audio_start(broadcast_source, adv); + if (err != 0) { + printk("Unable to start broadcast source: %d\n", err); + FAIL("Public Broadcast source failed\n"); + } + + err = setup_extended_adv_data(broadcast_source, adv); + if (err != 0) { + printk("Unable to setup extended advertising data: %d\n", err); + FAIL("Public Broadcast source failed\n"); + } + + err = start_extended_adv(adv); + if (err != 0) { + printk("Unable to start extended advertiser: %d\n", err); + FAIL("Public Broadcast source failed\n"); + } + + k_sem_take(&sem_started, SEM_TIMEOUT); + + /* Initialize sending */ + for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) { + sent_cb(&broadcast_stream->bap_stream); + } + + /* Keeping running for a little while */ + k_sleep(K_SECONDS(3)); + + err = bt_cap_initiator_broadcast_audio_stop(broadcast_source); + if (err != 0) { + printk("Failed to stop broadcast source: %d\n", err); + FAIL("Public Broadcast source failed\n"); + } + + k_sem_take(&sem_stopped, SEM_TIMEOUT); + err = bt_cap_initiator_broadcast_audio_delete(broadcast_source); + if (err != 0) { + printk("Failed to stop broadcast source: %d\n", err); + FAIL("Public Broadcast source failed\n"); + } + + broadcast_source = NULL; + + err = stop_extended_adv(adv); + if (err != 0) { + printk("Failed to stop and delete extended advertising: %d\n", err); + FAIL("Public Broadcast source failed\n"); + } + + count++; + } + + PASS("Public Broadcast source passed\n"); +} + +static const struct bst_test_instance test_pbp_broadcaster[] = { + { + .test_id = "public_broadcast_source", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main + }, + BSTEST_END_MARKER +}; + +struct bst_test_list *test_public_broadcast_source_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_pbp_broadcaster); +} + +#else /* CONFIG_BT_PBP */ + +struct bst_test_list *test_public_broadcast_source_install(struct bst_test_list *tests) +{ + return tests; +} + +#endif /* CONFIG_BT_PBP */ diff --git a/tests/bsim/bluetooth/audio/test_scripts/pbp.sh b/tests/bsim/bluetooth/audio/test_scripts/pbp.sh new file mode 100755 index 000000000000000..2a028e9f70f8e37 --- /dev/null +++ b/tests/bsim/bluetooth/audio/test_scripts/pbp.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 + +VERBOSITY_LEVEL=2 +EXECUTE_TIMEOUT=20 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +cd ${BSIM_OUT_PATH}/bin + +printf "\n\n======== Public Broadcaster test =========\n\n" + +SIMULATION_ID="pbp_broadcaster" + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=public_broadcast_source -rs=27 -D=2 + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=public_broadcast_sink -rs=27 -D=2 + +# Simulation time should be larger than the WAIT_TIME in common.h +Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ + -D=2 -sim_length=70e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/compile.sh b/tests/bsim/bluetooth/compile.sh index b6b709f84d23974..c0e3d813d721601 100755 --- a/tests/bsim/bluetooth/compile.sh +++ b/tests/bsim/bluetooth/compile.sh @@ -28,5 +28,8 @@ ${ZEPHYR_BASE}/tests/bsim/bluetooth/audio_samples/compile.sh ${ZEPHYR_BASE}/tests/bsim/bluetooth/host/compile.sh ${ZEPHYR_BASE}/tests/bsim/bluetooth/ll/compile.sh ${ZEPHYR_BASE}/tests/bsim/bluetooth/mesh/compile.sh +if [ ${BOARD} == "nrf52_bsim" ]; then + ${ZEPHYR_BASE}/tests/bsim/bluetooth/hci_uart/compile.sh +fi wait_for_background_jobs diff --git a/tests/bsim/bluetooth/hci_uart/compile.sh b/tests/bsim/bluetooth/hci_uart/compile.sh new file mode 100755 index 000000000000000..9eea0d52c382714 --- /dev/null +++ b/tests/bsim/bluetooth/hci_uart/compile.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Compile all the applications needed by the bsim tests in these subfolders + +#set -x #uncomment this line for debugging +set -ue +: "${BSIM_COMPONENTS_PATH:?BSIM_COMPONENTS_PATH must be defined}" +: "${ZEPHYR_BASE:?ZEPHYR_BASE must be set to point to the zephyr root\ + directory}" + +WORK_DIR="${WORK_DIR:-${ZEPHYR_BASE}/bsim_out}" + +BOARD_ROOT="${BOARD_ROOT:-${ZEPHYR_BASE}}" + +mkdir -p ${WORK_DIR} + +source ${ZEPHYR_BASE}/tests/bsim/compile.source + +app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_uart.conf compile +app=samples/bluetooth/hci_uart compile +app=samples/bluetooth/hci_uart_async compile + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_uart.sh b/tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_uart.sh new file mode 100755 index 000000000000000..765115ad449ca69 --- /dev/null +++ b/tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_uart.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Basic connection test: a central connects to a peripheral and expects a +# notification, using the split controller (ULL LLL) +# Both central and peripheral hosts have their controllers in a separate device +# connected over UART. The controller is the HCI UART sample. +simulation_id="basic_conn_split_uart" +verbosity_level=2 +EXECUTE_TIMEOUT=10 + +cd ${BSIM_OUT_PATH}/bin + +UART_DIR=/tmp/bs_${USER}/${simulation_id}/ +UART_PER=${UART_DIR}/peripheral +UART_CEN=${UART_DIR}/central + +# Note the host+app devices are NOT connected to the phy, only the controllers are. + +# Peripheral app + host : +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_conn_prj_split_uart_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=10 -nosim -RealEncryption=0 \ + -testid=peripheral -rs=23 -uart1_fifob_rxfile=${UART_PER}.rx -uart1_fifob_txfile=${UART_PER}.tx + +# Peripheral controller: +Execute ./bs_${BOARD}_samples_bluetooth_hci_uart_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=0 \ + -rs=23 -uart1_fifob_rxfile=${UART_PER}.tx -uart1_fifob_txfile=${UART_PER}.rx \ + +# Central app + host +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_conn_prj_split_uart_conf\ + -v=${verbosity_level} -s=${simulation_id} -d=11 -nosim -RealEncryption=0 \ + -testid=central -rs=6 -uart1_fifob_rxfile=${UART_CEN}.rx -uart1_fifob_txfile=${UART_CEN}.tx + +# Central controller: +Execute ./bs_${BOARD}_samples_bluetooth_hci_uart_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ + -rs=23 -uart1_fifob_rxfile=${UART_CEN}.tx -uart1_fifob_txfile=${UART_CEN}.rx + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_uart_async.sh b/tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_uart_async.sh new file mode 100755 index 000000000000000..ca2d9ea2ec8908e --- /dev/null +++ b/tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_uart_async.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Basic connection test: a central connects to a peripheral and expects a +# notification, using the split controller (ULL LLL) +# Both central and peripheral hosts have their controllers in a separate device +# connected over UART. The controller is the HCI UART async sample. +simulation_id="basic_conn_split_uart_async" +verbosity_level=2 +EXECUTE_TIMEOUT=10 + +cd ${BSIM_OUT_PATH}/bin + +UART_DIR=/tmp/bs_${USER}/${simulation_id}/ +UART_PER=${UART_DIR}/peripheral +UART_CEN=${UART_DIR}/central + +# Note the host+app devices are NOT connected to the phy, only the controllers are. + +# Peripheral app + host : +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_conn_prj_split_uart_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=10 -nosim -RealEncryption=0 \ + -testid=peripheral -rs=23 -uart1_fifob_rxfile=${UART_PER}.rx -uart1_fifob_txfile=${UART_PER}.tx + +# Peripheral controller: +Execute ./bs_${BOARD}_samples_bluetooth_hci_uart_async_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=0 \ + -rs=23 -uart1_fifob_rxfile=${UART_PER}.tx -uart1_fifob_txfile=${UART_PER}.rx + +# Central app + host +Execute ./bs_${BOARD}_tests_bsim_bluetooth_ll_conn_prj_split_uart_conf\ + -v=${verbosity_level} -s=${simulation_id} -d=11 -nosim -RealEncryption=0 \ + -testid=central -rs=6 -uart1_fifob_rxfile=${UART_CEN}.rx -uart1_fifob_txfile=${UART_CEN}.tx + +# Central controller: +Execute ./bs_${BOARD}_samples_bluetooth_hci_uart_async_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ + -rs=23 -uart1_fifob_rxfile=${UART_CEN}.tx -uart1_fifob_txfile=${UART_CEN}.rx + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/l2cap/stress/prj.conf b/tests/bsim/bluetooth/host/l2cap/stress/prj.conf index 3560a1b1f4be6ac..a28127716fcdd77 100644 --- a/tests/bsim/bluetooth/host/l2cap/stress/prj.conf +++ b/tests/bsim/bluetooth/host/l2cap/stress/prj.conf @@ -46,3 +46,10 @@ CONFIG_BT_MAX_CONN=10 CONFIG_LOG=y CONFIG_ASSERT=y CONFIG_NET_BUF_POOL_USAGE=y + +CONFIG_BT_L2CAP_LOG_LEVEL_DBG=y +# CONFIG_BT_CONN_LOG_LEVEL_DBG=y +CONFIG_LOG_THREAD_ID_PREFIX=y +CONFIG_THREAD_NAME=y + +CONFIG_ARCH_POSIX_TRAP_ON_FATAL=y diff --git a/tests/bsim/bluetooth/host/l2cap/stress/src/main.c b/tests/bsim/bluetooth/host/l2cap/stress/src/main.c index 08e988fcd363e1b..1eed057519b594b 100644 --- a/tests/bsim/bluetooth/host/l2cap/stress/src/main.c +++ b/tests/bsim/bluetooth/host/l2cap/stress/src/main.c @@ -23,20 +23,41 @@ CREATE_FLAG(flag_l2cap_connected); #define NUM_SEGMENTS 10 #define RESCHEDULE_DELAY K_MSEC(100) +static void sdu_destroy(struct net_buf *buf) +{ + LOG_DBG("%p", buf); + + net_buf_destroy(buf); +} + +static void segment_destroy(struct net_buf *buf) +{ + LOG_DBG("%p", buf); + + net_buf_destroy(buf); +} + +static void rx_destroy(struct net_buf *buf) +{ + LOG_DBG("%p", buf); + + net_buf_destroy(buf); +} + /* Only one SDU per link will be transmitted at a time */ NET_BUF_POOL_DEFINE(sdu_tx_pool, CONFIG_BT_MAX_CONN, BT_L2CAP_SDU_BUF_SIZE(SDU_LEN), - CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + CONFIG_BT_CONN_TX_USER_DATA_SIZE, sdu_destroy); NET_BUF_POOL_DEFINE(segment_pool, /* MTU + 4 l2cap hdr + 4 ACL hdr */ NUM_SEGMENTS, BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_TX_MTU), - CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + CONFIG_BT_CONN_TX_USER_DATA_SIZE, segment_destroy); /* Only one SDU per link will be received at a time */ NET_BUF_POOL_DEFINE(sdu_rx_pool, CONFIG_BT_MAX_CONN, BT_L2CAP_SDU_BUF_SIZE(SDU_LEN), - 8, NULL); + 8, rx_destroy); static uint8_t tx_data[SDU_LEN]; static uint16_t rx_cnt; diff --git a/tests/bsim/bluetooth/ll/bis/testcase.yaml b/tests/bsim/bluetooth/ll/bis/testcase.yaml new file mode 100644 index 000000000000000..ee619560a798fb2 --- /dev/null +++ b/tests/bsim/bluetooth/ll/bis/testcase.yaml @@ -0,0 +1,42 @@ +common: + build_only: true + tags: + - bluetooth + - bsim_multi + +tests: + bluetooth.ll.bis: + sysbuild: true + platform_allow: + - nrf52_bsim + - nrf5340bsim_nrf5340_cpuapp + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf52_bsim + - nrf5340bsim_nrf5340_cpuapp + - nrf5340bsim_nrf5340_cpunet + harness: bsim + harness_config: + bsim_exe_name: tests_bsim_bluetooth_ll_bis_prj_conf + bluetooth.ll.bis_ticker_expire_info: + extra_args: OVERLAY_CONFIG=overlay-ticker_expire_info.conf + platform_allow: + - nrf52_bsim + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf52_bsim + - nrf5340bsim_nrf5340_cpunet + harness: bsim + harness_config: + bsim_exe_name: tests_bsim_bluetooth_ll_bis_prj_conf_overlay-ticker_expire_info_conf + bluetooth.ll.bis_vs_dp: + extra_args: CONF_FILE=prj_vs_dp.conf + platform_allow: + - nrf52_bsim + - nrf5340bsim_nrf5340_cpunet + integration_platforms: + - nrf52_bsim + - nrf5340bsim_nrf5340_cpunet + harness: bsim + harness_config: + bsim_exe_name: tests_bsim_bluetooth_ll_bis_prj_vs_dp_conf diff --git a/tests/bsim/bluetooth/ll/conn/prj_split_uart.conf b/tests/bsim/bluetooth/ll/conn/prj_split_uart.conf new file mode 100644 index 000000000000000..bdc23cac294ef75 --- /dev/null +++ b/tests/bsim/bluetooth/ll/conn/prj_split_uart.conf @@ -0,0 +1,18 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_PRIVACY=y +CONFIG_BT_SMP=y +CONFIG_BT_SIGNING=y +CONFIG_BT_BAS=y +CONFIG_BT_HRS=y +CONFIG_BT_ATT_PREPARE_COUNT=2 +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BT_DEVICE_NAME="bsim_test_split_uart" +CONFIG_BT_L2CAP_TX_BUF_COUNT=6 + +CONFIG_BT_HCI=y +CONFIG_BT_CTLR=n +CONFIG_BT_H4=y diff --git a/tests/bsim/bluetooth/mesh/CMakeLists.txt b/tests/bsim/bluetooth/mesh/CMakeLists.txt index c6e09abe9c84248..f57b59c0c6408d8 100644 --- a/tests/bsim/bluetooth/mesh/CMakeLists.txt +++ b/tests/bsim/bluetooth/mesh/CMakeLists.txt @@ -9,6 +9,7 @@ target_sources(app PRIVATE src/main.c src/mesh_test.c src/friendship_common.c + src/gatt_common.c ) if(CONFIG_BT_MESH_V1d1) @@ -45,6 +46,7 @@ elseif(CONFIG_BT_MESH_GATT_PROXY) target_sources(app PRIVATE src/test_advertiser.c + src/test_suspend.c ) if(CONFIG_BT_MESH_V1d1) diff --git a/tests/bsim/bluetooth/mesh/compile.sh b/tests/bsim/bluetooth/mesh/compile.sh index de9b4bd6af0159e..4e3027a76818a71 100755 --- a/tests/bsim/bluetooth/mesh/compile.sh +++ b/tests/bsim/bluetooth/mesh/compile.sh @@ -35,5 +35,7 @@ app=tests/bsim/bluetooth/mesh \ conf_file=prj_mesh1d1.conf conf_overlay="overlay_gatt.conf;overlay_psa.conf" compile app=tests/bsim/bluetooth/mesh \ conf_file=prj_mesh1d1.conf conf_overlay="overlay_low_lat.conf;overlay_psa.conf" compile +app=tests/bsim/bluetooth/mesh \ + conf_file=prj_mesh1d1.conf conf_overlay="overlay_gatt.conf;overlay_low_lat.conf" compile wait_for_background_jobs diff --git a/tests/bsim/bluetooth/mesh/src/gatt_common.c b/tests/bsim/bluetooth/mesh/src/gatt_common.c new file mode 100644 index 000000000000000..ff57cebed714747 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/src/gatt_common.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "gatt_common.h" +#include +LOG_MODULE_REGISTER(gatt_common); + +void bt_mesh_test_parse_mesh_gatt_preamble(struct net_buf_simple *buf) +{ + ASSERT_EQUAL(0x0201, net_buf_simple_pull_be16(buf)); + /* flags */ + (void)net_buf_simple_pull_u8(buf); + ASSERT_EQUAL(0x0303, net_buf_simple_pull_be16(buf)); +} + +void bt_mesh_test_parse_mesh_pb_gatt_service(struct net_buf_simple *buf) +{ + /* MshPRT Figure 7.1: PB-GATT Advertising Data */ + /* mesh provisioning service */ + ASSERT_EQUAL(0x2718, net_buf_simple_pull_be16(buf)); + ASSERT_EQUAL(0x1516, net_buf_simple_pull_be16(buf)); + /* mesh provisioning service */ + ASSERT_EQUAL(0x2718, net_buf_simple_pull_be16(buf)); +} + +void bt_mesh_test_parse_mesh_proxy_service(struct net_buf_simple *buf) +{ + /* MshPRT Figure 7.2: Advertising with Network ID (Identification Type 0x00) */ + /* mesh proxy service */ + ASSERT_EQUAL(0x2818, net_buf_simple_pull_be16(buf)); + ASSERT_EQUAL(0x0c16, net_buf_simple_pull_be16(buf)); + /* mesh proxy service */ + ASSERT_EQUAL(0x2818, net_buf_simple_pull_be16(buf)); + /* network ID */ + ASSERT_EQUAL(0x00, net_buf_simple_pull_u8(buf)); +} diff --git a/tests/bsim/bluetooth/mesh/src/gatt_common.h b/tests/bsim/bluetooth/mesh/src/gatt_common.h new file mode 100644 index 000000000000000..4904325cdb29ab3 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/src/gatt_common.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mesh_test.h" + +enum bt_mesh_test_gatt_service { + MESH_SERVICE_PROVISIONING, + MESH_SERVICE_PROXY, +}; + +struct bt_mesh_test_gatt { + uint8_t transmits; /* number of frame (pb gatt or proxy beacon) transmits */ + int64_t interval; /* interval of transmitted frames */ + enum bt_mesh_test_gatt_service service; +}; + +struct bt_mesh_test_adv { + uint8_t retr; /* number of retransmits of adv frame */ + int64_t interval; /* interval of transmitted frames */ +}; + +void bt_mesh_test_parse_mesh_gatt_preamble(struct net_buf_simple *buf); +void bt_mesh_test_parse_mesh_pb_gatt_service(struct net_buf_simple *buf); +void bt_mesh_test_parse_mesh_proxy_service(struct net_buf_simple *buf); diff --git a/tests/bsim/bluetooth/mesh/src/main.c b/tests/bsim/bluetooth/mesh/src/main.c index 67544e494d00771..4b28d506627964a 100644 --- a/tests/bsim/bluetooth/mesh/src/main.c +++ b/tests/bsim/bluetooth/mesh/src/main.c @@ -19,6 +19,7 @@ extern struct bst_test_list *test_sar_pst_install(struct bst_test_list *test); #endif /* defined(CONFIG_BT_MESH_V1d1) */ #elif defined(CONFIG_BT_MESH_GATT_PROXY) extern struct bst_test_list *test_adv_install(struct bst_test_list *test); +extern struct bst_test_list *test_suspend_install(struct bst_test_list *test); #if defined(CONFIG_BT_MESH_V1d1) extern struct bst_test_list *test_beacon_install(struct bst_test_list *tests); #endif /* defined(CONFIG_BT_MESH_V1d1) */ @@ -59,6 +60,7 @@ bst_test_install_t test_installers[] = { #endif /* defined(CONFIG_BT_MESH_V1d1) */ #elif defined(CONFIG_BT_MESH_GATT_PROXY) test_adv_install, + test_suspend_install, #if defined(CONFIG_BT_MESH_V1d1) test_beacon_install, #endif /* defined(CONFIG_BT_MESH_V1d1) */ diff --git a/tests/bsim/bluetooth/mesh/src/mesh_test.c b/tests/bsim/bluetooth/mesh/src/mesh_test.c index 5dce0c8dc9d3b8a..2a73d1f47186fba 100644 --- a/tests/bsim/bluetooth/mesh/src/mesh_test.c +++ b/tests/bsim/bluetooth/mesh/src/mesh_test.c @@ -7,6 +7,7 @@ #include "argparse.h" #include #include "mesh/crypto.h" +#include #define LOG_MODULE_NAME mesh_test @@ -546,6 +547,50 @@ uint16_t bt_mesh_test_own_addr_get(uint16_t start_addr) return start_addr + get_device_nbr(); } +void bt_mesh_test_send_over_adv(void *data, size_t len) +{ + struct bt_mesh_adv *adv = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL, + BT_MESH_TRANSMIT(0, 20), K_NO_WAIT); + net_buf_simple_add_mem(&adv->b, data, len); + bt_mesh_adv_send(adv, NULL, NULL); +} + +int bt_mesh_test_wait_for_packet(bt_le_scan_cb_t scan_cb, struct k_sem *observer_sem, uint16_t wait) +{ + struct bt_le_scan_param scan_param = { + .type = BT_HCI_LE_SCAN_PASSIVE, + .options = BT_LE_SCAN_OPT_NONE, + .interval = BT_MESH_ADV_SCAN_UNIT(1000), + .window = BT_MESH_ADV_SCAN_UNIT(1000) + }; + int err; + int returned_value = 0; + + err = bt_le_scan_start(&scan_param, scan_cb); + if (err && err != -EALREADY) { + LOG_ERR("Starting scan failed (err %d)", err); + return err; + } + + err = k_sem_take(observer_sem, K_SECONDS(wait)); + if (err == -EAGAIN) { + LOG_WRN("Taking sem timed out (err %d)", err); + returned_value = -EAGAIN; + } else if (err) { + LOG_ERR("Taking sem failed (err %d)", err); + return err; + } + + err = bt_le_scan_stop(); + if (err && err != -EALREADY) { + LOG_ERR("Stopping scan failed (err %d)", err); + return err; + } + + return returned_value; +} + + #if defined(CONFIG_BT_MESH_SAR_CFG) void bt_mesh_test_sar_conf_set(struct bt_mesh_sar_tx *tx_set, struct bt_mesh_sar_rx *rx_set) { diff --git a/tests/bsim/bluetooth/mesh/src/mesh_test.h b/tests/bsim/bluetooth/mesh/src/mesh_test.h index 3dcaa5f784aaea2..d3af115c8814b26 100644 --- a/tests/bsim/bluetooth/mesh/src/mesh_test.h +++ b/tests/bsim/bluetooth/mesh/src/mesh_test.h @@ -23,6 +23,7 @@ #include #include +#include #define TEST_MOD_ID 0x8888 #define TEST_MSG_OP_1 BT_MESH_MODEL_OP_1(0x0f) @@ -202,6 +203,13 @@ void bt_mesh_test_ra_cb_setup(void (*cb)(uint8_t *, size_t)); uint16_t bt_mesh_test_own_addr_get(uint16_t start_addr); +void bt_mesh_test_send_over_adv(void *data, size_t len); +/* Wait for a packet (i. e. an advertisement or a GATT frame) sent by a device. + * `scan_cb` is triggered if the packet is received, and must release `observer_sem` when finished. + */ +int bt_mesh_test_wait_for_packet(bt_le_scan_cb_t scan_cb, struct k_sem *observer_sem, + uint16_t wait); + #if defined(CONFIG_BT_MESH_SAR_CFG) void bt_mesh_test_sar_conf_set(struct bt_mesh_sar_tx *tx_set, struct bt_mesh_sar_rx *rx_set); #endif diff --git a/tests/bsim/bluetooth/mesh/src/test_advertiser.c b/tests/bsim/bluetooth/mesh/src/test_advertiser.c index 47851fc72f4a68d..0ddb5fba6ce3a76 100644 --- a/tests/bsim/bluetooth/mesh/src/test_advertiser.c +++ b/tests/bsim/bluetooth/mesh/src/test_advertiser.c @@ -10,6 +10,7 @@ #include "mesh/net.h" #include "mesh/mesh.h" #include "mesh/foundation.h" +#include "gatt_common.h" #define LOG_MODULE_NAME test_adv @@ -18,22 +19,6 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF); #define WAIT_TIME 60 /*seconds*/ -enum bt_mesh_gatt_service { - MESH_SERVICE_PROVISIONING, - MESH_SERVICE_PROXY, -}; - -struct bt_mesh_test_adv { - uint8_t retr; /* number of retransmits of adv frame */ - int64_t interval; /* interval of transmitted frames */ -}; - -struct bt_mesh_test_gatt { - uint8_t transmits; /* number of frame (pb gatt or proxy beacon) transmits */ - int64_t interval; /* interval of transmitted frames */ - enum bt_mesh_gatt_service service; -}; - extern const struct bt_mesh_comp comp; static uint8_t test_prov_uuid[16] = { 0x6c, 0x69, 0x6e, 0x67, 0x61, 0xaa }; @@ -183,36 +168,6 @@ static void seq_end_cb(int err, void *cb_data) } } -static void parse_mesh_gatt_preamble(struct net_buf_simple *buf) -{ - ASSERT_EQUAL(0x0201, net_buf_simple_pull_be16(buf)); - /* flags */ - (void)net_buf_simple_pull_u8(buf); - ASSERT_EQUAL(0x0303, net_buf_simple_pull_be16(buf)); -} - -static void parse_mesh_pb_gatt_service(struct net_buf_simple *buf) -{ - /* Figure 7.1: PB-GATT Advertising Data */ - /* mesh provisioning service */ - ASSERT_EQUAL(0x2718, net_buf_simple_pull_be16(buf)); - ASSERT_EQUAL(0x1516, net_buf_simple_pull_be16(buf)); - /* mesh provisioning service */ - ASSERT_EQUAL(0x2718, net_buf_simple_pull_be16(buf)); -} - -static void parse_mesh_proxy_service(struct net_buf_simple *buf) -{ - /* Figure 7.2: Advertising with Network ID (Identification Type 0x00) */ - /* mesh proxy service */ - ASSERT_EQUAL(0x2818, net_buf_simple_pull_be16(buf)); - ASSERT_EQUAL(0x0c16, net_buf_simple_pull_be16(buf)); - /* mesh proxy service */ - ASSERT_EQUAL(0x2818, net_buf_simple_pull_be16(buf)); - /* network ID */ - ASSERT_EQUAL(0x00, net_buf_simple_pull_u8(buf)); -} - static void gatt_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, struct net_buf_simple *buf) { @@ -220,12 +175,12 @@ static void gatt_scan_cb(const bt_addr_le_t *addr, int8_t rssi, return; } - parse_mesh_gatt_preamble(buf); + bt_mesh_test_parse_mesh_gatt_preamble(buf); if (gatt_param.service == MESH_SERVICE_PROVISIONING) { - parse_mesh_pb_gatt_service(buf); + bt_mesh_test_parse_mesh_pb_gatt_service(buf); } else { - parse_mesh_proxy_service(buf); + bt_mesh_test_parse_mesh_proxy_service(buf); } LOG_INF("rx: %s", txt_msg); @@ -236,26 +191,6 @@ static void gatt_scan_cb(const bt_addr_le_t *addr, int8_t rssi, } } -static void rx_gatt_beacons(void) -{ - struct bt_le_scan_param scan_param = { - .type = BT_HCI_LE_SCAN_PASSIVE, - .options = BT_LE_SCAN_OPT_NONE, - .interval = BT_MESH_ADV_SCAN_UNIT(1000), - .window = BT_MESH_ADV_SCAN_UNIT(1000) - }; - int err; - - err = bt_le_scan_start(&scan_param, gatt_scan_cb); - ASSERT_FALSE_MSG(err && err != -EALREADY, "Starting scan failed (err %d)\n", err); - - err = k_sem_take(&observer_sem, K_SECONDS(20)); - ASSERT_OK(err); - - err = bt_le_scan_stop(); - ASSERT_FALSE_MSG(err && err != -EALREADY, "Stopping scan failed (err %d)\n", err); -} - static void xmit_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, struct net_buf_simple *buf) { @@ -282,26 +217,6 @@ static void xmit_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type } } -static void rx_xmit_adv(void) -{ - struct bt_le_scan_param scan_param = { - .type = BT_HCI_LE_SCAN_PASSIVE, - .options = BT_LE_SCAN_OPT_NONE, - .interval = BT_MESH_ADV_SCAN_UNIT(1000), - .window = BT_MESH_ADV_SCAN_UNIT(1000) - }; - int err; - - err = bt_le_scan_start(&scan_param, xmit_scan_cb); - ASSERT_FALSE_MSG(err && err != -EALREADY, "Starting scan failed (err %d)\n", err); - - err = k_sem_take(&observer_sem, K_SECONDS(20)); - ASSERT_OK(err); - - err = bt_le_scan_stop(); - ASSERT_FALSE_MSG(err && err != -EALREADY, "Stopping scan failed (err %d)\n", err); -} - static void send_order_start_cb(uint16_t duration, int err, void *user_data) { struct bt_mesh_adv *adv = (struct bt_mesh_adv *)user_data; @@ -355,25 +270,10 @@ static void receive_order_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t static void receive_order(int expect_adv) { - struct bt_le_scan_param scan_param = { - .type = BT_HCI_LE_SCAN_PASSIVE, - .options = BT_LE_SCAN_OPT_NONE, - .interval = BT_MESH_ADV_SCAN_UNIT(1000), - .window = BT_MESH_ADV_SCAN_UNIT(1000) - }; - int err; - - err = bt_le_scan_start(&scan_param, receive_order_scan_cb); - ASSERT_FALSE_MSG(err && err != -EALREADY, "Starting scan failed (err %d)\n", err); - previous_checker = 0xff; for (int i = 0; i < expect_adv; i++) { - err = k_sem_take(&observer_sem, K_SECONDS(10)); - ASSERT_OK_MSG(err, "Didn't receive adv in time"); + ASSERT_OK(bt_mesh_test_wait_for_packet(receive_order_scan_cb, &observer_sem, 10)); } - - err = bt_le_scan_stop(); - ASSERT_FALSE_MSG(err && err != -EALREADY, "Stopping scan failed (err %d)\n", err); } static void send_adv_buf(struct bt_mesh_adv *adv, uint8_t curr, uint8_t prev) @@ -446,7 +346,7 @@ static void test_rx_xmit(void) xmit_param.interval = 20; bt_init(); - rx_xmit_adv(); + ASSERT_OK(bt_mesh_test_wait_for_packet(xmit_scan_cb, &observer_sem, 20)); PASS(); } @@ -548,7 +448,7 @@ static void test_rx_proxy_mixin(void) bt_init(); /* Scan pb gatt beacons. */ - rx_gatt_beacons(); + ASSERT_OK(bt_mesh_test_wait_for_packet(gatt_scan_cb, &observer_sem, 20)); /* Delay to provision dut */ k_sleep(K_MSEC(1000)); @@ -558,15 +458,15 @@ static void test_rx_proxy_mixin(void) gatt_param.transmits = 5000 / 1000; gatt_param.interval = 1000; gatt_param.service = MESH_SERVICE_PROXY; - rx_gatt_beacons(); + ASSERT_OK(bt_mesh_test_wait_for_packet(gatt_scan_cb, &observer_sem, 20)); /* Scan adv data. */ xmit_param.retr = 5; xmit_param.interval = 20; - rx_xmit_adv(); + ASSERT_OK(bt_mesh_test_wait_for_packet(xmit_scan_cb, &observer_sem, 20)); /* Scan proxy beacons again. */ - rx_gatt_beacons(); + ASSERT_OK(bt_mesh_test_wait_for_packet(gatt_scan_cb, &observer_sem, 20)); PASS(); } diff --git a/tests/bsim/bluetooth/mesh/src/test_beacon.c b/tests/bsim/bluetooth/mesh/src/test_beacon.c index 938b5dc141a4f47..69dbad1f24c4bc2 100644 --- a/tests/bsim/bluetooth/mesh/src/test_beacon.c +++ b/tests/bsim/bluetooth/mesh/src/test_beacon.c @@ -387,23 +387,9 @@ static void beacon_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_ty static bool wait_for_beacon(bt_le_scan_cb_t scan_cb, uint16_t wait, bool (*process_cb)(const uint8_t *net_id, void *ctx), void *ctx) { - struct bt_le_scan_param scan_param = { - .type = BT_HCI_LE_SCAN_PASSIVE, - .options = BT_LE_SCAN_OPT_NONE, - .interval = BT_MESH_ADV_SCAN_UNIT(1000), - .window = BT_MESH_ADV_SCAN_UNIT(1000) - }; - bool received = false; - int err; - beacon.process_cb = process_cb; beacon.user_ctx = ctx; - err = bt_le_scan_start(&scan_param, scan_cb); - if (err && err != -EALREADY) { - FAIL("starting scan failed (err %d)", err); - } - /* Listen to beacons ONLY for one beacon interval. * Tests start quite often the waiting for the next beacon after * transmission or receiving the previous one. If start waiting timer @@ -413,17 +399,7 @@ static bool wait_for_beacon(bt_le_scan_cb_t scan_cb, uint16_t wait, * waiting time (BEACON_INTERVAL + 1) to guarantee that beacon comes * before timer expiration. */ - err = k_sem_take(&observer_sem, K_SECONDS(wait)); - if (!err) { - received = true; - } else { - LOG_WRN("Didn't receive beacon in time (err: %d)", err); - } - - err = bt_le_scan_stop(); - if (err && err != -EALREADY) { - FAIL("stopping scan failed (err %d)", err); - } + bool received = !bt_mesh_test_wait_for_packet(scan_cb, &observer_sem, wait); /* Sleep a little to get to the next beacon interval. Otherwise, calling this function * again will catch the old beacon. This happens due to a known bug in legacy advertiser, @@ -2011,6 +1987,8 @@ static const struct bt_mesh_test_cfg solicit_trigger_cfg = { static void test_tx_proxy_adv_solicit_trigger(void) { tx_proxy_adv_common_init(PROXY_ADV_MULTI_SUBNET_COEX_WAIT_TIME, &solicit_trigger_cfg); + /* Disable SNB. */ + bt_mesh_beacon_set(false); ASSERT_OK_MSG(bt_mesh_subnet_add(TEST_NET_IDX2, test_net_key_2), "Failed to add second subnet"); @@ -2028,6 +2006,8 @@ static void test_tx_proxy_adv_solicit_trigger(void) static void test_rx_proxy_adv_multi_subnet_coex(void) { rx_priv_common_init(PROXY_ADV_MULTI_SUBNET_COEX_WAIT_TIME); + /* Disable SNB. */ + bt_mesh_beacon_set(false); pp_netkey_ctx_init(&pp_net1); pp_netkey_ctx_init(&pp_net2); @@ -2071,10 +2051,10 @@ static void test_rx_proxy_adv_multi_subnet_coex(void) /** The first and second subnet gets solicited. Check that * PRIVATE_NET_ID is advertised by these subnet, */ - {.evt_type = BEACON_TYPE_PRIVATE_NET_ID, .net_idx = 0, .evt_cnt = 9, + {.evt_type = BEACON_TYPE_PRIVATE_NET_ID, .net_idx = 0, .evt_cnt = 8, .time = {.after = PROXY_ADV_MULTI_CHECKPOINT_3, .before = PROXY_ADV_MULTI_CHECKPOINT_4}}, - {.evt_type = BEACON_TYPE_PRIVATE_NET_ID, .net_idx = 1, .evt_cnt = 9, + {.evt_type = BEACON_TYPE_PRIVATE_NET_ID, .net_idx = 1, .evt_cnt = 8, .time = {.after = PROXY_ADV_MULTI_CHECKPOINT_3, .before = PROXY_ADV_MULTI_CHECKPOINT_4}}, diff --git a/tests/bsim/bluetooth/mesh/src/test_suspend.c b/tests/bsim/bluetooth/mesh/src/test_suspend.c index a83ee0259099998..63ad49d802f5c4d 100644 --- a/tests/bsim/bluetooth/mesh/src/test_suspend.c +++ b/tests/bsim/bluetooth/mesh/src/test_suspend.c @@ -6,45 +6,53 @@ */ #include "mesh_test.h" +#include "gatt_common.h" #include #include -#include #include LOG_MODULE_REGISTER(test_suspend, LOG_LEVEL_INF); #define WAIT_TIME 60 /* seconds */ #define SUSPEND_DURATION 15 /* seconds */ -#define NUM_PUB 4 /* Times the transmitter will publish per interval. */ +#define NUM_PUB 4 /* Times the DUT will publish per interval. */ #define TEST_MODEL_ID_1 0x2a2a #define TEST_MODEL_ID_2 0x2b2b #define TEST_MESSAGE_OP 0x1f +enum dut_mesh_status { + DUT_SUSPENDED, + DUT_RUNNING, +}; + static int model_1_init(const struct bt_mesh_model *model); static int model_2_init(const struct bt_mesh_model *model); static uint8_t app_key[16] = {0xaa}; static uint8_t net_key[16] = {0xcc}; -static const struct bt_mesh_test_cfg tx_cfg = { +static const struct bt_mesh_test_cfg dut_cfg = { .addr = 0x00a0, .dev_key = {0x01}, }; -static const struct bt_mesh_test_cfg rx_cfg = { +static const struct bt_mesh_test_cfg tester_cfg = { .addr = 0x00b0, .dev_key = {0x02}, }; -static struct bt_mesh_prov prov; +static uint8_t test_prov_uuid[16] = { 0x6c, 0x69, 0x6e, 0x67, 0x61, 0xaa }; +static struct bt_mesh_prov prov = { + .uuid = test_prov_uuid, + }; static struct k_sem publish_sem; -static bool suspended; +static enum dut_mesh_status dut_status; static int model_1_update(const struct bt_mesh_model *model) { model->pub->msg->data[1]++; - LOG_INF("Model 1 publishing..., n: %d", model->pub->msg->data[1]); + LOG_DBG("Model 1 publishing..., n: %d", model->pub->msg->data[1]); k_sem_give(&publish_sem); return 0; } @@ -53,16 +61,32 @@ static int msg_handler(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx struct net_buf_simple *buf) { static uint8_t prev_num; + static int64_t uptime; uint8_t num = net_buf_simple_pull_u8(buf); - LOG_INF("Received msg, n: %d", num); + LOG_DBG("Received msg, n: %d", num); /* Ensure that payload changes. */ ASSERT_TRUE(prev_num != num); prev_num = num; - /* Ensure that no message is received while Mesh is suspended or disabled. */ - ASSERT_FALSE_MSG(suspended, "Received publication while Mesh is suspended."); + /* Ensure that no message is received while Mesh is suspended or disabled. + * A publication may be sent just before DUT is suspended, which is ignored. + */ + if ((dut_status == DUT_SUSPENDED) && !(num == (NUM_PUB + 1))) { + if (SUSPEND_DURATION * 1000ll <= k_uptime_delta(&uptime)) { + dut_status = DUT_RUNNING; + LOG_DBG("Suspend duration passed. Setting status to %d.", dut_status); + } else { + FAIL("Received publication while Mesh is suspended."); + } + } + + if (num == NUM_PUB) { + dut_status = DUT_SUSPENDED; + LOG_DBG("Expected number of pubs received. Setting status to %d.", dut_status); + uptime = k_uptime_get(); + } k_sem_give(&publish_sem); return 0; @@ -83,42 +107,42 @@ static const struct bt_mesh_model_op model_op_1[] = {BT_MESH_MODEL_OP_END}; static const struct bt_mesh_model_op model_op_2[] = {{TEST_MESSAGE_OP, 0, msg_handler}, BT_MESH_MODEL_OP_END}; -static struct bt_mesh_cfg_cli cfg_cli_tx; -static struct bt_mesh_model tx_models[] = { +static struct bt_mesh_cfg_cli cfg_cli_dut; +static struct bt_mesh_model dut_models[] = { BT_MESH_MODEL_CFG_SRV, - BT_MESH_MODEL_CFG_CLI(&cfg_cli_tx), + BT_MESH_MODEL_CFG_CLI(&cfg_cli_dut), BT_MESH_MODEL_CB(TEST_MODEL_ID_1, model_op_1, &model_1_pub, NULL, &model_1_cb), }; -static struct bt_mesh_elem tx_elems[] = { - BT_MESH_ELEM(0, tx_models, BT_MESH_MODEL_NONE), +static struct bt_mesh_elem dut_elems[] = { + BT_MESH_ELEM(0, dut_models, BT_MESH_MODEL_NONE), }; -static const struct bt_mesh_comp tx_comp = { +static const struct bt_mesh_comp dut_comp = { .cid = TEST_VND_COMPANY_ID, .vid = 0xeeee, .pid = 0xaaaa, - .elem = tx_elems, - .elem_count = ARRAY_SIZE(tx_elems), + .elem = dut_elems, + .elem_count = ARRAY_SIZE(dut_elems), }; -static struct bt_mesh_cfg_cli cfg_cli_rx; -static struct bt_mesh_model rx_models[] = { +static struct bt_mesh_cfg_cli cfg_cli_tester; +static struct bt_mesh_model tester_models[] = { BT_MESH_MODEL_CFG_SRV, - BT_MESH_MODEL_CFG_CLI(&cfg_cli_rx), + BT_MESH_MODEL_CFG_CLI(&cfg_cli_tester), BT_MESH_MODEL_CB(TEST_MODEL_ID_2, model_op_2, NULL, NULL, &model_2_cb), }; -static struct bt_mesh_elem rx_elems[] = { - BT_MESH_ELEM(0, rx_models, BT_MESH_MODEL_NONE), +static struct bt_mesh_elem tester_elems[] = { + BT_MESH_ELEM(0, tester_models, BT_MESH_MODEL_NONE), }; -static const struct bt_mesh_comp rx_comp = { +static const struct bt_mesh_comp tester_comp = { .cid = TEST_VND_COMPANY_ID, .vid = 0xbaaa, .pid = 0xb000, - .elem = rx_elems, - .elem_count = ARRAY_SIZE(rx_elems), + .elem = tester_elems, + .elem_count = ARRAY_SIZE(tester_elems), }; static int model_1_init(const struct bt_mesh_model *model) @@ -134,7 +158,7 @@ static int model_2_init(const struct bt_mesh_model *model) return 0; } -static void provision_and_configure(struct bt_mesh_test_cfg cfg, bool rx) +static void provision_and_configure(struct bt_mesh_test_cfg cfg, bool tester) { int err; uint8_t status; @@ -146,8 +170,8 @@ static void provision_and_configure(struct bt_mesh_test_cfg cfg, bool rx) FAIL("AppKey add failed (err %d, status %u)", err, status); } - const struct bt_mesh_test_cfg *pcfg = rx ? &rx_cfg : &tx_cfg; - uint16_t model_id = rx ? TEST_MODEL_ID_2 : TEST_MODEL_ID_1; + const struct bt_mesh_test_cfg *pcfg = tester ? &tester_cfg : &dut_cfg; + uint16_t model_id = tester ? TEST_MODEL_ID_2 : TEST_MODEL_ID_1; err = bt_mesh_cfg_cli_mod_app_bind(0, pcfg->addr, pcfg->addr, 0, model_id, &status); if (err || status) { @@ -156,7 +180,7 @@ static void provision_and_configure(struct bt_mesh_test_cfg cfg, bool rx) } struct bt_mesh_cfg_cli_mod_pub pub_params = { - .addr = rx_cfg.addr, + .addr = tester_cfg.addr, .uuid = NULL, .cred_flag = false, .app_idx = 0, @@ -165,79 +189,103 @@ struct bt_mesh_cfg_cli_mod_pub pub_params = { .transmit = 0, }; -static void test_tx_suspend_resume(void) +extern const struct bt_mesh_comp comp; +/* For legacy adv, pb-gatt advs are sent with a 1000ms interval. For ext adv, they are sent + * with a 100ms interval. + */ +static struct bt_mesh_test_gatt gatt_param = { +#if defined(CONFIG_BT_EXT_ADV) + /* (total transmit duration) / (transmit interval) */ + .transmits = 1500 / 100, + .interval = 100, +#else + .transmits = 2000 / 1000, + .interval = 1000, +#endif + .service = MESH_SERVICE_PROVISIONING, +}; + +static bool gatt_check_rx_count(uint8_t transmit) { - bt_mesh_test_cfg_set(NULL, WAIT_TIME); - bt_mesh_device_setup(&prov, &tx_comp); - provision_and_configure(tx_cfg, 0); + static int cnt; - k_sem_init(&publish_sem, 0, 1); - suspended = false; - uint8_t status; - int err; + LOG_DBG("rx: cnt(%d)", cnt); + cnt++; - err = bt_mesh_cfg_cli_mod_pub_set(0, tx_cfg.addr, tx_cfg.addr, TEST_MODEL_ID_1, &pub_params, - &status); - if (err || status) { - FAIL("Mod pub set failed (err %d, status %u)", err, status); + if (cnt >= transmit) { + cnt = 0; + return true; } - /* Wait until node has published before suspending. */ - for (int i = 0; i < NUM_PUB; i++) { - ASSERT_OK_MSG(k_sem_take(&publish_sem, K_SECONDS(30)), "Pub timed out"); - } + return false; +} - ASSERT_OK(bt_mesh_suspend()); - suspended = true; - LOG_INF("Mesh suspended."); +static void gatt_scan_cb(const bt_addr_le_t *addr, int8_t rssi, + uint8_t adv_type, struct net_buf_simple *buf) +{ + if (adv_type != BT_GAP_ADV_TYPE_ADV_IND) { + return; + } - k_sleep(K_SECONDS(SUSPEND_DURATION)); + /* Ensure that no message is received while Mesh is suspended or disabled. */ + ASSERT_FALSE_MSG(dut_status == DUT_SUSPENDED, "Received adv while Mesh is suspended."); - ASSERT_OK(bt_mesh_resume()); - suspended = false; - LOG_INF("Mesh resumed."); + bt_mesh_test_parse_mesh_gatt_preamble(buf); - for (int i = 0; i < NUM_PUB; i++) { - ASSERT_OK_MSG(k_sem_take(&publish_sem, K_SECONDS(30)), "Pub timed out"); + if (gatt_param.service == MESH_SERVICE_PROVISIONING) { + LOG_DBG("Parsing pb_gatt adv"); + bt_mesh_test_parse_mesh_pb_gatt_service(buf); + } else { + LOG_DBG("Parsing proxy adv"); + bt_mesh_test_parse_mesh_proxy_service(buf); } - /* Allow publishing to finish before suspending. */ - k_sleep(K_MSEC(100)); - ASSERT_OK(bt_mesh_suspend()); - - PASS(); + if (gatt_check_rx_count(gatt_param.transmits)) { + LOG_DBG("rx completed, stopping scan..."); + k_sem_give(&publish_sem); + } } -static void test_rx_suspend_resume(void) +static void suspend_state_change_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, + struct net_buf_simple *buf) { - bt_mesh_test_cfg_set(NULL, WAIT_TIME); - bt_mesh_device_setup(&prov, &rx_comp); - provision_and_configure(rx_cfg, 1); - k_sem_init(&publish_sem, 0, 1); + uint8_t length; - /* Receive messages before and after suspending. A publication may get lost - * when suspending immeditiately after publication, thus the "-1". - */ - for (int i = 0; i < NUM_PUB * 2 - 1; i++) { - ASSERT_OK_MSG(k_sem_take(&publish_sem, K_SECONDS(30)), "Receiver timed out"); + if (adv_type != BT_GAP_ADV_TYPE_ADV_NONCONN_IND) { + return; } - PASS(); + length = net_buf_simple_pull_u8(buf); + ASSERT_EQUAL(buf->len, length); + ASSERT_EQUAL(length, sizeof(uint8_t) + sizeof(enum dut_mesh_status)); + ASSERT_EQUAL(BT_DATA_MESH_MESSAGE, net_buf_simple_pull_u8(buf)); + + enum dut_mesh_status *msg_status = + net_buf_simple_pull_mem(buf, sizeof(enum dut_mesh_status)); + + if ((*msg_status == DUT_RUNNING) || (*msg_status == DUT_SUSPENDED)) { + dut_status = *msg_status; + } else { + FAIL("Received unexpected data"); + } + + LOG_DBG("Received %d from DUT, setting status to %s", + *msg_status, (dut_status == DUT_SUSPENDED) ? "true" : "false"); + k_sem_give(&publish_sem); } -static void test_tx_suspend_disable_resume(void) +static void dut_pub_common(bool disable_bt) { bt_mesh_test_cfg_set(NULL, WAIT_TIME); - bt_mesh_device_setup(&prov, &tx_comp); - provision_and_configure(tx_cfg, 0); + bt_mesh_device_setup(&prov, &dut_comp); + provision_and_configure(dut_cfg, 0); k_sem_init(&publish_sem, 0, 1); - suspended = false; uint8_t status; int err; - err = bt_mesh_cfg_cli_mod_pub_set(0, tx_cfg.addr, tx_cfg.addr, TEST_MODEL_ID_1, &pub_params, - &status); + err = bt_mesh_cfg_cli_mod_pub_set(0, dut_cfg.addr, dut_cfg.addr, TEST_MODEL_ID_1, + &pub_params, &status); if (err || status) { FAIL("Mod pub set failed (err %d, status %u)", err, status); } @@ -247,21 +295,19 @@ static void test_tx_suspend_disable_resume(void) ASSERT_OK_MSG(k_sem_take(&publish_sem, K_SECONDS(30)), "Pub timed out"); } - ASSERT_OK(bt_mesh_suspend()); - suspended = true; - LOG_INF("Mesh suspended."); + ASSERT_OK_MSG(bt_mesh_suspend(), "Failed to suspend Mesh."); - ASSERT_OK(bt_disable()); - LOG_INF("Bluetooth disabled."); + if (disable_bt) { + ASSERT_OK_MSG(bt_disable(), "Failed to disable Bluetooth."); + } k_sleep(K_SECONDS(SUSPEND_DURATION)); - ASSERT_OK(bt_enable(NULL)); - LOG_INF("Bluetooth enabled."); + if (disable_bt) { + ASSERT_OK_MSG(bt_enable(NULL), "Failed to enable Bluetooth."); + } - ASSERT_OK(bt_mesh_resume()); - suspended = false; - LOG_INF("Mesh resumed."); + ASSERT_OK_MSG(bt_mesh_resume(), "Failed to resume Mesh."); for (int i = 0; i < NUM_PUB; i++) { ASSERT_OK_MSG(k_sem_take(&publish_sem, K_SECONDS(30)), "Pub timed out"); @@ -270,15 +316,70 @@ static void test_tx_suspend_disable_resume(void) /* Allow publishing to finish before suspending. */ k_sleep(K_MSEC(100)); ASSERT_OK(bt_mesh_suspend()); +} + +static void dut_gatt_common(bool disable_bt) +{ + bt_mesh_test_cfg_set(NULL, WAIT_TIME); + bt_mesh_device_setup(&prov, &comp); + ASSERT_OK_MSG(bt_mesh_prov_enable(BT_MESH_PROV_GATT), "Failed to enable GATT provisioner"); + dut_status = DUT_RUNNING; + /* Let the Tester observe pb gatt advertisements before provisioning. The node should + * advertise pb gatt service with 100 msec (ext adv) or 1000msec (legacy adv) interval. + */ + k_sleep(K_MSEC(1800)); + + ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, 0, dut_cfg.addr, dut_cfg.dev_key)); + + /* Let the Tester observe proxy advertisements */ + k_sleep(K_MSEC(6500)); + + /* Send a mesh message to notify Tester that DUT is about to be suspended. */ + dut_status = DUT_SUSPENDED; + bt_mesh_test_send_over_adv(&dut_status, sizeof(enum dut_mesh_status)); + k_sleep(K_MSEC(150)); + + ASSERT_OK_MSG(bt_mesh_suspend(), "Failed to suspend Mesh."); + + if (disable_bt) { + ASSERT_OK_MSG(bt_disable(), "Failed to disable Bluetooth."); + } + + k_sleep(K_SECONDS(SUSPEND_DURATION)); + + if (disable_bt) { + ASSERT_OK_MSG(bt_enable(NULL), "Failed to enable Bluetooth."); + } + + ASSERT_OK_MSG(bt_mesh_resume(), "Failed to resume Mesh."); + + /* Send a mesh message to notify Tester that device is resumed */ + dut_status = DUT_RUNNING; + bt_mesh_test_send_over_adv(&dut_status, sizeof(enum dut_mesh_status)); + + /* Let the Tester observe that proxy advertisement resumes */ + k_sleep(K_MSEC(6000)); +} + +static void test_dut_suspend_resume(void) +{ + dut_pub_common(false); + PASS(); +} + +static void test_dut_suspend_disable_resume(void) +{ + dut_pub_common(true); PASS(); } -static void test_rx_suspend_disable_resume(void) +static void test_tester_pub(void) { bt_mesh_test_cfg_set(NULL, WAIT_TIME); - bt_mesh_device_setup(&prov, &rx_comp); - provision_and_configure(rx_cfg, 1); + bt_mesh_device_setup(&prov, &tester_comp); + provision_and_configure(tester_cfg, 1); k_sem_init(&publish_sem, 0, 1); + dut_status = DUT_RUNNING; /* Receive messages before and after suspending. A publication may get lost * when suspending immeditiately after publication, thus the "-1". @@ -290,6 +391,54 @@ static void test_rx_suspend_disable_resume(void) PASS(); } +static void test_dut_gatt_suspend_resume(void) +{ + dut_gatt_common(false); + PASS(); +} + +static void test_dut_gatt_suspend_disable_resume(void) +{ + dut_gatt_common(true); + PASS(); +} + +static void test_tester_gatt(void) +{ + k_sem_init(&publish_sem, 0, 1); + dut_status = DUT_RUNNING; + int err; + + ASSERT_OK_MSG(bt_enable(NULL), "Bluetooth init failed"); + + /* Scan pb gatt beacons. */ + ASSERT_OK(bt_mesh_test_wait_for_packet(gatt_scan_cb, &publish_sem, 10)); + + /* Delay to provision DUT */ + k_sleep(K_MSEC(1000)); + + /* Scan gatt proxy beacons. */ + /* (total transmit duration) / (transmit interval) */ + gatt_param.transmits = 5000 / 1000; + gatt_param.interval = 1000; + gatt_param.service = MESH_SERVICE_PROXY; + ASSERT_OK(bt_mesh_test_wait_for_packet(gatt_scan_cb, &publish_sem, 10)); + + /* Allow DUT to suspend before scanning for gatt proxy beacons */ + ASSERT_OK(bt_mesh_test_wait_for_packet(suspend_state_change_cb, &publish_sem, 20)); + ASSERT_EQUAL(dut_status, DUT_SUSPENDED); + k_sleep(K_MSEC(500)); + err = bt_mesh_test_wait_for_packet(gatt_scan_cb, &publish_sem, 10); + ASSERT_FALSE(err && err != -EAGAIN); + + /* Wait for DUT to resume Mesh and notify Tester, then scan for gatt proxy beacons */ + ASSERT_OK(bt_mesh_test_wait_for_packet(suspend_state_change_cb, &publish_sem, 20)); + ASSERT_EQUAL(dut_status, DUT_RUNNING); + ASSERT_OK(bt_mesh_test_wait_for_packet(gatt_scan_cb, &publish_sem, 10)); + + PASS(); +} + #define TEST_CASE(role, name, description) \ { \ .test_id = "suspend_" #role "_" #name, .test_descr = description, \ @@ -297,11 +446,17 @@ static void test_rx_suspend_disable_resume(void) } static const struct bst_test_instance test_suspend[] = { - TEST_CASE(tx, suspend_resume, "tx suspend resume"), - TEST_CASE(tx, suspend_disable_resume, "tx suspend, disable resume"), - - TEST_CASE(rx, suspend_resume, "rx suspend resume"), - TEST_CASE(rx, suspend_disable_resume, "rx suspend, disable resume"), + TEST_CASE(dut, suspend_resume, + "Suspend and resume Mesh with periodic pub"), + TEST_CASE(dut, suspend_disable_resume, + "Suspend and resume Mesh (and disable/enable BT) with periodic pub"), + TEST_CASE(dut, gatt_suspend_resume, + "Suspend and resume Mesh with GATT proxy advs"), + TEST_CASE(dut, gatt_suspend_disable_resume, + "Suspend and resume Mesh (and disable/enable BT) with GATT proxy advs"), + + TEST_CASE(tester, pub, "Scan and verify behavior of periodic publishing adv"), + TEST_CASE(tester, gatt, "Scan and verify behavior of GATT proxy adv"), BSTEST_END_MARKER}; diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/proxy_adv_multi_subnet_coex.sh b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/proxy_adv_multi_subnet_coex.sh index aa96ee325d8789f..845a8ff7da73ad8 100755 --- a/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/proxy_adv_multi_subnet_coex.sh +++ b/tests/bsim/bluetooth/mesh/tests_scripts/priv_beacon/proxy_adv_multi_subnet_coex.sh @@ -22,6 +22,10 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh # window. The Mesh Protocol specification does not specify exactly the # timing for Proxy ADV messages. +# Note 3: The proxy transmitting device mandates emitting of the secure +# network beacons. This allows to check that proxy goes back to normal +# behavior after device advertises the seure network beacons. + # Test procedure: # 1. (0-20 seconds) A single subnet is active on the TX device with GATT # Proxy enabled. RX device verifies that the single subnet has exclusive diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/suspend/gatt_suspend_disable_resume.sh b/tests/bsim/bluetooth/mesh/tests_scripts/suspend/gatt_suspend_disable_resume.sh new file mode 100755 index 000000000000000..c723ea38610a29f --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/suspend/gatt_suspend_disable_resume.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that GATT advertisement is stopped when suspending Mesh and disabling +# Bluetooth, and that it is started again when Bluetooth is re-enabled and Mesh is resumed. +# +# Test procedure: +# 0. DUT (Device 0) initializes the Mesh stack, and starts provisioning procedure using +# bt_mesh_prov_enable(BT_MESH_PROV_GATT). +# 1. Tester (Device 1) observes PB-GATT advs, and will fail the test if the expected +# amount of advs is not received. +# 2. DUT is provisioned, and Tester observes GATT proxy advs. +# 3. DUT notifies the Tester that it will be suspended, and Tester observes for advs after a +# brief delay. Receiving an adv while DUT is suspended will cause the test to fail. +# 4. After a delay, the DUT resumes and notifies the Tester, which checks that the +# advertising resumes. + +overlay=overlay_gatt_conf +RunTest mesh_gatt_suspend_disable_resume \ + suspend_dut_gatt_suspend_disable_resume suspend_tester_gatt + +conf=prj_mesh1d1_conf +overlay="overlay_gatt_conf_overlay_low_lat_conf" +RunTest mesh_gatt_suspend_disable_resume_low_lat \ + suspend_dut_gatt_suspend_disable_resume suspend_tester_gatt + +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf +RunTest mesh_gatt_suspend_disable_resume_1d1 \ + suspend_dut_gatt_suspend_disable_resume suspend_tester_gatt + +conf=prj_mesh1d1_conf +overlay="overlay_gatt_conf_overlay_psa_conf" +RunTest mesh_gatt_suspend_disable_resume_psa \ + suspend_dut_gatt_suspend_disable_resume suspend_tester_gatt diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/suspend/gatt_suspend_resume.sh b/tests/bsim/bluetooth/mesh/tests_scripts/suspend/gatt_suspend_resume.sh new file mode 100755 index 000000000000000..dc29ecfeadf6e1e --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/suspend/gatt_suspend_resume.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Copyright 2023 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test that GATT advertisement is stopped when suspending Mesh, and that it is started again +# when Mesh is resumed. +# +# Test procedure: +# 0. DUT (Device 0) initializes the Mesh stack, and starts provisioning procedure using +# bt_mesh_prov_enable(BT_MESH_PROV_GATT). +# 1. Tester (Device 1) observes PB-GATT advs, and will fail the test if the expected +# amount of advs is not received. +# 2. DUT is provisioned, and Tester observes GATT proxy advs. +# 3. DUT notifies the Tester that it will be suspended, and Tester observes for advs after a +# brief delay. Receiving an adv while DUT is suspended will cause the test to fail. +# 4. After a delay, the DUT resumes and notifies the Tester, which checks that the +# advertising resumes. + +overlay=overlay_gatt_conf +RunTest mesh_gatt_suspend_resume \ + suspend_dut_gatt_suspend_resume suspend_tester_gatt + +conf=prj_mesh1d1_conf +overlay="overlay_gatt_conf_overlay_low_lat_conf" +RunTest mesh_gatt_suspend_resume_low_lat \ + suspend_dut_gatt_suspend_resume suspend_tester_gatt + +conf=prj_mesh1d1_conf +overlay=overlay_gatt_conf +RunTest mesh_gatt_suspend_resume_1d1 \ + suspend_dut_gatt_suspend_resume suspend_tester_gatt + +conf=prj_mesh1d1_conf +overlay="overlay_gatt_conf_overlay_psa_conf" +RunTest mesh_gatt_suspend_resume_psa \ + suspend_dut_gatt_suspend_resume suspend_tester_gatt diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/suspend/suspend_disable_resume.sh b/tests/bsim/bluetooth/mesh/tests_scripts/suspend/suspend_disable_resume.sh index 6390b2e193ccbca..3329cc2d2bd3772 100755 --- a/tests/bsim/bluetooth/mesh/tests_scripts/suspend/suspend_disable_resume.sh +++ b/tests/bsim/bluetooth/mesh/tests_scripts/suspend/suspend_disable_resume.sh @@ -17,17 +17,17 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh # Check that publication resumes. RunTest mesh_suspend_disable_resume \ - suspend_tx_suspend_disable_resume suspend_rx_suspend_disable_resume + suspend_dut_suspend_disable_resume suspend_tester_pub conf=prj_mesh1d1_conf RunTest mesh_suspend_disable_resume_1d1 \ - suspend_tx_suspend_disable_resume suspend_rx_suspend_disable_resume + suspend_dut_suspend_disable_resume suspend_tester_pub overlay=overlay_low_lat_conf RunTest mesh_suspend_disable_resume_low_lat \ - suspend_tx_suspend_disable_resume suspend_rx_suspend_disable_resume + suspend_dut_suspend_disable_resume suspend_tester_pub conf=prj_mesh1d1_conf overlay=overlay_psa_conf RunTest mesh_suspend_disable_resume_psa \ - suspend_tx_suspend_disable_resume suspend_rx_suspend_disable_resume + suspend_dut_suspend_disable_resume suspend_tester_pub diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/suspend/suspend_resume.sh b/tests/bsim/bluetooth/mesh/tests_scripts/suspend/suspend_resume.sh index 5d4da84a1654043..90e1623b62bc358 100755 --- a/tests/bsim/bluetooth/mesh/tests_scripts/suspend/suspend_resume.sh +++ b/tests/bsim/bluetooth/mesh/tests_scripts/suspend/suspend_resume.sh @@ -16,17 +16,17 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh # 3. Resume Mesh a specified time after suspension. Check that publication resumes. RunTest mesh_suspend_resume \ - suspend_tx_suspend_resume suspend_rx_suspend_resume + suspend_dut_suspend_resume suspend_tester_pub conf=prj_mesh1d1_conf RunTest mesh_suspend_resume_1d1 \ - suspend_tx_suspend_resume suspend_rx_suspend_resume + suspend_dut_suspend_resume suspend_tester_pub overlay=overlay_low_lat_conf RunTest mesh_suspend_resume_low_lat \ - suspend_tx_suspend_resume suspend_rx_suspend_resume + suspend_dut_suspend_resume suspend_tester_pub conf=prj_mesh1d1_conf overlay=overlay_psa_conf RunTest mesh_suspend_resume_psa \ - suspend_tx_suspend_resume suspend_rx_suspend_resume + suspend_dut_suspend_resume suspend_tester_pub diff --git a/tests/drivers/build_all/adc/boards/native_sim.overlay b/tests/drivers/build_all/adc/boards/native_sim.overlay index 120e05dcfb0726c..cc7ac9a45e210ce 100644 --- a/tests/drivers/build_all/adc/boards/native_sim.overlay +++ b/tests/drivers/build_all/adc/boards/native_sim.overlay @@ -140,7 +140,7 @@ reg = <0x1>; spi-max-frequency = <0>; drdyb-gpios = <&test_gpio 0 0>; - #io-channel-cells = <2>; + #io-channel-cells = <1>; }; test_spi_lmp90078: lmp90078@2 { @@ -148,7 +148,7 @@ reg = <0x2>; spi-max-frequency = <0>; drdyb-gpios = <&test_gpio 0 0>; - #io-channel-cells = <2>; + #io-channel-cells = <1>; }; test_spi_lmp90079: lmp90079@3 { @@ -156,7 +156,7 @@ reg = <0x3>; spi-max-frequency = <0>; drdyb-gpios = <&test_gpio 0 0>; - #io-channel-cells = <2>; + #io-channel-cells = <1>; }; test_spi_lmp90080: lmp90080@4 { @@ -164,7 +164,7 @@ reg = <0x4>; spi-max-frequency = <0>; drdyb-gpios = <&test_gpio 0 0>; - #io-channel-cells = <2>; + #io-channel-cells = <1>; }; test_spi_lmp90097: lmp90097@5 { @@ -172,7 +172,7 @@ reg = <0x5>; spi-max-frequency = <0>; drdyb-gpios = <&test_gpio 0 0>; - #io-channel-cells = <2>; + #io-channel-cells = <1>; }; test_spi_lmp90098: lmp90098@6 { @@ -180,7 +180,7 @@ reg = <0x6>; spi-max-frequency = <0>; drdyb-gpios = <&test_gpio 0 0>; - #io-channel-cells = <2>; + #io-channel-cells = <1>; }; test_spi_lmp90099: lmp90099@7 { @@ -188,7 +188,7 @@ reg = <0x7>; spi-max-frequency = <0>; drdyb-gpios = <&test_gpio 0 0>; - #io-channel-cells = <2>; + #io-channel-cells = <1>; }; test_spi_lmp90100: lmp90100@8 { @@ -196,7 +196,7 @@ reg = <0x8>; spi-max-frequency = <0>; drdyb-gpios = <&test_gpio 0 0>; - #io-channel-cells = <2>; + #io-channel-cells = <1>; }; test_spi_ads7052: ads7052@9 { diff --git a/tests/drivers/build_all/charger/i2c.dtsi b/tests/drivers/build_all/charger/i2c.dtsi index c30efdcfcb8e3d6..b6365e97470bd1a 100644 --- a/tests/drivers/build_all/charger/i2c.dtsi +++ b/tests/drivers/build_all/charger/i2c.dtsi @@ -28,3 +28,9 @@ max20335@1 { constant-charge-voltage-max-microvolt = <4050000>; }; }; + +bq25180@2 { + compatible = "ti,bq25180"; + reg = <0x2>; + constant-charge-current-max-microamp = <500000>; +}; diff --git a/tests/drivers/build_all/input/app.overlay b/tests/drivers/build_all/input/app.overlay index 0a005414667165f..d1baa128237da36 100644 --- a/tests/drivers/build_all/input/app.overlay +++ b/tests/drivers/build_all/input/app.overlay @@ -9,6 +9,22 @@ #address-cells = <1>; #size-cells = <1>; + test_adc: adc@adc0adc0 { + compatible = "vnd,adc"; + reg = <0xadc0adc0 0x1000>; + #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,acquisition-time = ; + }; + }; + test_gpio: gpio@0 { compatible = "vnd,gpio"; gpio-controller; @@ -26,6 +42,16 @@ }; }; + gpio-keys-polled { + compatible = "gpio-keys"; + debounce-interval-ms = <30>; + button_0 { + gpios = <&test_gpio 0 0>; + zephyr,code = <0>; + }; + polling-mode; + }; + evdev { compatible = "zephyr,native-linux-evdev"; }; @@ -71,6 +97,20 @@ idle-timeout-ms = <200>; }; + analog_axis { + compatible = "analog-axis"; + axis-x { + io-channels = <&test_adc 0>; + out-min = <(-127)>; + out-max = <127>; + out-deadzone = <8>; + in-min = <(-100)>; + in-max = <100>; + zephyr,axis = <0>; + invert; + }; + }; + longpress: longpress { input = <&longpress>; compatible = "zephyr,input-longpress"; diff --git a/tests/drivers/build_all/input/testcase.yaml b/tests/drivers/build_all/input/testcase.yaml index eb915db16737677..2c3883ab062ee99 100644 --- a/tests/drivers/build_all/input/testcase.yaml +++ b/tests/drivers/build_all/input/testcase.yaml @@ -19,3 +19,8 @@ tests: drivers.input.kbd_16_bit: extra_configs: - CONFIG_INPUT_KBD_MATRIX_16_BIT_ROW=y + + drivers.input.analog_axis: + extra_configs: + - CONFIG_ADC=y + - CONFIG_SETTINGS=y diff --git a/tests/drivers/build_all/interrupt_controller/intc_plic/testcase.yaml b/tests/drivers/build_all/interrupt_controller/intc_plic/testcase.yaml index ea80ccf8d2627e5..290a889ba89d3c0 100644 --- a/tests/drivers/build_all/interrupt_controller/intc_plic/testcase.yaml +++ b/tests/drivers/build_all/interrupt_controller/intc_plic/testcase.yaml @@ -10,6 +10,12 @@ common: - plic tests: drivers.interrupt_controller.intc_plic.build: {} + drivers.interrupt_controller.intc_plic.plic_shell.build: + tags: + - shell + extra_configs: + - CONFIG_SHELL=y + - CONFIG_PLIC_SHELL=y drivers.interrupt_controller.intc_plic.multi_instance.build: extra_args: DTC_OVERLAY_FILE="./app.multi_instance.overlay" diff --git a/tests/drivers/build_all/w1/CMakeLists.txt b/tests/drivers/build_all/w1/CMakeLists.txt new file mode 100644 index 000000000000000..b627b17c503adf3 --- /dev/null +++ b/tests/drivers/build_all/w1/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Hudson C. Dalpra +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(build_all) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/build_all/w1/app.overlay b/tests/drivers/build_all/w1/app.overlay new file mode 100644 index 000000000000000..aa11ce6c168a958 --- /dev/null +++ b/tests/drivers/build_all/w1/app.overlay @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Hudson C. Dalpra + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for testing driver builds + * + * Names in this file should be chosen in a way that won't conflict + * with real-world devicetree nodes, to allow these tests to run on + * (and be extended to test) real hardware. + */ + +/ { + test { + #address-cells = <1>; + #size-cells = <1>; + + test_gpio: gpio@deadbeef { + compatible = "vnd,gpio"; + gpio-controller; + reg = <0xdeadbeef 0x1000>; + #gpio-cells = <0x2>; + status = "okay"; + }; + + test_w1_gpio: test_w1_gpio { + compatible = "zephyr,w1-gpio"; + gpios = <&test_gpio 0 0>; + }; + }; +}; diff --git a/tests/drivers/build_all/w1/prj.conf b/tests/drivers/build_all/w1/prj.conf new file mode 100644 index 000000000000000..f9de5e1757804a0 --- /dev/null +++ b/tests/drivers/build_all/w1/prj.conf @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Hudson C. Dalpra +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_TEST=y +CONFIG_TEST_USERSPACE=y +CONFIG_GPIO=y +CONFIG_W1=y diff --git a/tests/drivers/build_all/w1/src/main.c b/tests/drivers/build_all/w1/src/main.c new file mode 100644 index 000000000000000..98bfd327335c314 --- /dev/null +++ b/tests/drivers/build_all/w1/src/main.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2023 Hudson C. Dalpra + * + * SPDX-License-Identifier: Apache-2.0 + */ + +int main(void) +{ + return 0; +} diff --git a/tests/drivers/build_all/w1/testcase.yaml b/tests/drivers/build_all/w1/testcase.yaml new file mode 100644 index 000000000000000..f0e1d11aeb91cdd --- /dev/null +++ b/tests/drivers/build_all/w1/testcase.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Hudson C. Dalpra +# SPDX-License-Identifier: Apache-2.0 + +tests: + drivers.w1.build: + build_only: true + tags: + - drivers + - w1 + integration_platforms: + - native_posix diff --git a/tests/drivers/counter/counter_basic_api/src/test_counter.c b/tests/drivers/counter/counter_basic_api/src/test_counter.c index f63ee5ce6c46cf6..370b07b248ca246 100644 --- a/tests/drivers/counter/counter_basic_api/src/test_counter.c +++ b/tests/drivers/counter/counter_basic_api/src/test_counter.c @@ -99,6 +99,9 @@ static const struct device *const devices[] = { #ifdef CONFIG_COUNTER_TIMER_RPI_PICO DEVS_FOR_DT_COMPAT(raspberrypi_pico_timer) #endif +#ifdef CONFIG_COUNTER_AMBIQ + DEVS_FOR_DT_COMPAT(ambiq_counter) +#endif }; static const struct device *const period_devs[] = { diff --git a/tests/drivers/eeprom/api/src/main.c b/tests/drivers/eeprom/api/src/main.c index e9ddd3ec76f59a5..5a14565cccb3bc8 100644 --- a/tests/drivers/eeprom/api/src/main.c +++ b/tests/drivers/eeprom/api/src/main.c @@ -178,7 +178,7 @@ static void run_tests_on_eeprom(const struct device *dev) printk("Running tests on device \"%s\"\n", eeprom->name); k_object_access_grant(eeprom, k_current_get()); - ztest_run_all(NULL); + ztest_run_all(NULL, false, 1, 1); } void test_main(void) diff --git a/tests/drivers/gpio/gpio_ite_it8xxx2_v2/CMakeLists.txt b/tests/drivers/gpio/gpio_ite_it8xxx2_v2/CMakeLists.txt index bf01055ffc36d0b..1079605a2b41788 100644 --- a/tests/drivers/gpio/gpio_ite_it8xxx2_v2/CMakeLists.txt +++ b/tests/drivers/gpio/gpio_ite_it8xxx2_v2/CMakeLists.txt @@ -13,8 +13,8 @@ target_include_directories(app PRIVATE zephyr_include_directories( include - ${ZEPHYR_BASE}/soc/riscv/riscv-ite/common - ${ZEPHYR_BASE}/soc/riscv/riscv-ite/it8xxx2 + ${ZEPHYR_BASE}/soc/riscv/ite_ec/common + ${ZEPHYR_BASE}/soc/riscv/ite_ec/it8xxx2 ) target_sources(app diff --git a/tests/drivers/gpio/gpio_ite_it8xxx2_v2/include/chip_chipregs.h b/tests/drivers/gpio/gpio_ite_it8xxx2_v2/include/chip_chipregs.h index 3372a845aa95500..d3c1f7c827eb139 100644 --- a/tests/drivers/gpio/gpio_ite_it8xxx2_v2/include/chip_chipregs.h +++ b/tests/drivers/gpio/gpio_ite_it8xxx2_v2/include/chip_chipregs.h @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include <../soc/riscv/riscv-ite/common/chip_chipregs.h> +#include <../soc/riscv/ite_ec/common/chip_chipregs.h> /* * Macros for emulated hardware registers access. diff --git a/tests/drivers/memc/ram/testcase.yaml b/tests/drivers/memc/ram/testcase.yaml index 0fac2dea9b4b3af..5d9f768b8bbf897 100644 --- a/tests/drivers/memc/ram/testcase.yaml +++ b/tests/drivers/memc/ram/testcase.yaml @@ -21,6 +21,8 @@ tests: integration_platforms: - sam4s_xplained drivers.memc.sifive_ddr: + simulation_exclude: + - renode tags: - drivers - memc diff --git a/tests/drivers/pwm/pwm_loopback/boards/ucans32k1sic.overlay b/tests/drivers/pwm/pwm_loopback/boards/ucans32k1sic.overlay new file mode 100644 index 000000000000000..01c43d6a27b2374 --- /dev/null +++ b/tests/drivers/pwm/pwm_loopback/boards/ucans32k1sic.overlay @@ -0,0 +1,43 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + pwm_loopback_0 { + compatible = "test-pwm-loopback"; + pwms = <&ftm1 1 0 PWM_POLARITY_NORMAL>, /* PTB3, P1.3 */ + <&ftm0 4 0 PWM_POLARITY_NORMAL>; /* PTB4, P1.4 */ + }; +}; + +&pinctrl { + ftm0_loopback: ftm0_loopback { + group0 { + pinmux = ; + drive-strength = "low"; + }; + }; + + ftm1_loopback: ftm1_loopback { + group0 { + pinmux = ; + drive-strength = "low"; + }; + }; +}; + +&ftm0 { + pinctrl-0 = <&ftm0_loopback>; + prescaler = <32>; + status = "okay"; +}; + +&ftm1 { + pinctrl-0 = <&ftm1_loopback>; + prescaler = <128>; + status = "okay"; +}; diff --git a/tests/drivers/smbus/smbus_emul/src/smbus.c b/tests/drivers/smbus/smbus_emul/src/smbus.c index d42a22d1a23f82b..9a96722684d28ec 100644 --- a/tests/drivers/smbus/smbus_emul/src/smbus.c +++ b/tests/drivers/smbus/smbus_emul/src/smbus.c @@ -181,7 +181,7 @@ ZTEST(test_smbus_emul, test_proc_call) zassert_ok(ret, "SMBus Proc Call failed"); /* Our emulated Proc Call swaps bytes */ - zassert_equal(snd_word, __bswap_16(rcv_word), "Data mismatch"); + zassert_equal(snd_word, BSWAP_16(rcv_word), "Data mismatch"); } ZTEST(test_smbus_emul, test_block) diff --git a/tests/drivers/uart/uart_async_api/boards/nrf52_bsim.overlay b/tests/drivers/uart/uart_async_api/boards/nrf52_bsim.overlay new file mode 100644 index 000000000000000..c7277e73775c858 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf52_bsim.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf52840dk_nrf52840.overlay" diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_async.c b/tests/drivers/uart/uart_async_api/src/test_uart_async.c index 9579e49c759bebf..26c8de398978bce 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart_async.c +++ b/tests/drivers/uart/uart_async_api/src/test_uart_async.c @@ -233,7 +233,7 @@ ZTEST_USER(uart_async_multi_rx, test_multiple_rx_enable) const uint32_t rx_buf_size = sizeof(tx_buf); int ret; - BUILD_ASSERT(rx_buf_size <= sizeof(tdata.rx_first_buffer), "Invalid buf size"); + BUILD_ASSERT(sizeof(tx_buf) <= sizeof(tdata.rx_first_buffer), "Invalid buf size"); /* Enable RX without a timeout. */ ret = uart_rx_enable(uart_dev, tdata.rx_first_buffer, rx_buf_size, SYS_FOREVER_US); diff --git a/tests/drivers/uart/uart_async_rx/prj.conf b/tests/drivers/uart/uart_async_rx/prj.conf index eb88c509ea7e9f4..56dee84a9e5b4b1 100644 --- a/tests/drivers/uart/uart_async_rx/prj.conf +++ b/tests/drivers/uart/uart_async_rx/prj.conf @@ -1,3 +1,4 @@ CONFIG_ZTEST=y CONFIG_ZTRESS=y CONFIG_UART_ASYNC_RX_HELPER=y +CONFIG_SERIAL=y diff --git a/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf52_bsim.overlay b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf52_bsim.overlay new file mode 100644 index 000000000000000..c7277e73775c858 --- /dev/null +++ b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf52_bsim.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf52840dk_nrf52840.overlay" diff --git a/tests/drivers/uart/uart_pm/boards/nrf52_bsim.overlay b/tests/drivers/uart/uart_pm/boards/nrf52_bsim.overlay new file mode 100644 index 000000000000000..c7277e73775c858 --- /dev/null +++ b/tests/drivers/uart/uart_pm/boards/nrf52_bsim.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf52840dk_nrf52840.overlay" diff --git a/tests/kernel/gen_isr_table/testcase.yaml b/tests/kernel/gen_isr_table/testcase.yaml index 29c4316dafa71fd..292a801080b573e 100644 --- a/tests/kernel/gen_isr_table/testcase.yaml +++ b/tests/kernel/gen_isr_table/testcase.yaml @@ -53,7 +53,7 @@ tests: platform_exclude: - m2gl025_miv - adp_xc7k_ae350 - filter: CONFIG_SOC_FAMILY_RISCV_PRIVILEGED + filter: CONFIG_RISCV_PRIVILEGED extra_configs: - CONFIG_GEN_IRQ_VECTOR_TABLE=y arch.interrupt.gen_isr_table.riscv_no_direct: @@ -61,18 +61,18 @@ tests: arch_allow: - riscv32 - riscv64 - filter: CONFIG_SOC_FAMILY_RISCV_PRIVILEGED + filter: CONFIG_RISCV_PRIVILEGED extra_configs: - CONFIG_GEN_IRQ_VECTOR_TABLE=n arch.interrupt.gen_isr_table.bit_shift_2nd_level: platform_allow: qemu_riscv32 - filter: CONFIG_SOC_FAMILY_RISCV_PRIVILEGED + filter: CONFIG_RISCV_PRIVILEGED extra_configs: - CONFIG_1ST_LEVEL_INTERRUPT_BITS=7 - CONFIG_2ND_LEVEL_INTERRUPT_BITS=9 arch.interrupt.gen_isr_table.bit_shift_3rd_level: platform_allow: qemu_riscv32 - filter: CONFIG_SOC_FAMILY_RISCV_PRIVILEGED + filter: CONFIG_RISCV_PRIVILEGED extra_configs: - CONFIG_MULTI_LEVEL_INTERRUPTS=y - CONFIG_2ND_LEVEL_INTERRUPTS=y diff --git a/tests/kernel/sleep/src/main.c b/tests/kernel/sleep/src/main.c index 89da43b82ca828f..9ef991b8647cdbf 100644 --- a/tests/kernel/sleep/src/main.c +++ b/tests/kernel/sleep/src/main.c @@ -72,8 +72,6 @@ static void test_objects_init(void) k_sem_init(&test_thread_sem, 0, UINT_MAX); k_sem_init(&helper_thread_sem, 0, UINT_MAX); k_sem_init(&task_sem, 0, UINT_MAX); - - TC_PRINT("Kernel objects initialized\n"); } static void align_to_tick_boundary(void) @@ -111,7 +109,6 @@ static void test_thread(void *p1, void *p2, void *p3) k_sem_take(&test_thread_sem, K_FOREVER); - TC_PRINT("Testing normal expiration of k_sleep()\n"); align_to_tick_boundary(); start_tick = k_uptime_get_32(); @@ -125,7 +122,6 @@ static void test_thread(void *p1, void *p2, void *p3) return; } - TC_PRINT("Testing: test thread sleep + helper thread wakeup test\n"); k_sem_give(&helper_thread_sem); /* Activate helper thread */ align_to_tick_boundary(); @@ -139,7 +135,6 @@ static void test_thread(void *p1, void *p2, void *p3) return; } - TC_PRINT("Testing: test thread sleep + isr offload wakeup test\n"); k_sem_give(&helper_thread_sem); /* Activate helper thread */ align_to_tick_boundary(); @@ -153,7 +148,6 @@ static void test_thread(void *p1, void *p2, void *p3) return; } - TC_PRINT("Testing: test thread sleep + main wakeup test thread\n"); k_sem_give(&task_sem); /* Activate task */ align_to_tick_boundary(); @@ -216,16 +210,12 @@ ZTEST(sleep, test_sleep) 0, 0, NULL, TEST_THREAD_PRIORITY, 0, K_NO_WAIT); - TC_PRINT("Test thread started: id = %p\n", test_thread_id); - helper_thread_id = k_thread_create(&helper_thread_data, helper_thread_stack, THREAD_STACK, helper_thread, 0, 0, NULL, HELPER_THREAD_PRIORITY, 0, K_NO_WAIT); - TC_PRINT("Helper thread started: id = %p\n", helper_thread_id); - /* Activate test_thread */ k_sem_give(&test_thread_sem); @@ -237,7 +227,6 @@ ZTEST(sleep, test_sleep) zassert_false(test_failure, "test failure"); - TC_PRINT("Testing kernel k_sleep()\n"); align_to_tick_boundary(); start_tick = k_uptime_get_32(); k_sleep(K_SECONDS(1)); diff --git a/tests/kernel/sleep/src/usleep.c b/tests/kernel/sleep/src/usleep.c index 67037e593c90606..b7c1144505a225b 100644 --- a/tests/kernel/sleep/src/usleep.c +++ b/tests/kernel/sleep/src/usleep.c @@ -89,7 +89,6 @@ ZTEST_USER(sleep, test_usleep) } } - printk("elapsed_ms = %" PRId64 "\n", elapsed_ms); zassert_true(elapsed_ms >= LOWER_BOUND_MS, "short sleep"); zassert_true(elapsed_ms <= UPPER_BOUND_MS, "overslept"); } diff --git a/tests/kernel/threads/thread_apis/src/main.c b/tests/kernel/threads/thread_apis/src/main.c index b68c433110192bc..2e4a4b90f456c55 100644 --- a/tests/kernel/threads/thread_apis/src/main.c +++ b/tests/kernel/threads/thread_apis/src/main.c @@ -43,7 +43,7 @@ static ZTEST_DMEM int tp = 10; */ ZTEST(threads_lifecycle, test_systhreads_main) { - zassert_true(main_prio == CONFIG_MAIN_THREAD_PRIORITY); + zassert_true(main_prio == CONFIG_MAIN_THREAD_PRIORITY, "%d", CONFIG_MAIN_THREAD_PRIORITY); } /** @@ -185,7 +185,7 @@ ZTEST_USER(threads_lifecycle, test_thread_name_user_get_set) zassert_equal(ret, -EINVAL, "not a thread object"); ret = k_thread_name_copy(&z_main_thread, thread_name, sizeof(thread_name)); - zassert_equal(ret, 0, "couldn't get main thread name"); + zassert_equal(ret, 0, "couldn't get main thread name: %s (%d)", thread_name, ret); LOG_DBG("Main thread name is '%s'", thread_name); /* Set and get child thread's name */ diff --git a/tests/kernel/timer/timer_behavior/src/main.c b/tests/kernel/timer/timer_behavior/src/main.c index f3806198e8abe0d..427b88b75d2aee0 100644 --- a/tests/kernel/timer/timer_behavior/src/main.c +++ b/tests/kernel/timer/timer_behavior/src/main.c @@ -8,8 +8,8 @@ void test_main(void) { - ztest_run_test_suite(timer_jitter_drift); + ztest_run_test_suite(timer_jitter_drift, false, 1, 1); #ifndef CONFIG_TIMER_EXTERNAL_TEST - ztest_run_test_suite(timer_tick_train); + ztest_run_test_suite(timer_tick_train, false, 1, 1); #endif } diff --git a/tests/lib/cpp/cxx/src/main.cpp b/tests/lib/cpp/cxx/src/main.cpp index 43bc14f65acd1ee..dd377c015b8da81 100644 --- a/tests/lib/cpp/cxx/src/main.cpp +++ b/tests/lib/cpp/cxx/src/main.cpp @@ -17,7 +17,6 @@ #include #include #include -/* #include conflicts with __bswapXX on native_posix */ #include #include diff --git a/tests/lib/devicetree/devices/testcase.yaml b/tests/lib/devicetree/devices/testcase.yaml index 27be9c7c9e1c2bb..47e8d6cf9f94a11 100644 --- a/tests/lib/devicetree/devices/testcase.yaml +++ b/tests/lib/devicetree/devices/testcase.yaml @@ -18,3 +18,4 @@ tests: - mimxrt595_evk_cm33 - nrf9131ek_nrf9131 - nrf9131ek_nrf9131_ns + - kincony_kc868_a32 diff --git a/tests/net/lib/lwm2m/lwm2m_engine/boards/qemu_x86.conf b/tests/net/lib/lwm2m/lwm2m_engine/boards/qemu_x86.conf new file mode 100644 index 000000000000000..c735e1a8a2d6d0c --- /dev/null +++ b/tests/net/lib/lwm2m/lwm2m_engine/boards/qemu_x86.conf @@ -0,0 +1 @@ +CONFIG_TEST_EXTRA_STACK_SIZE=1024 diff --git a/tests/net/socket/tls/src/main.c b/tests/net/socket/tls/src/main.c index 1e81e2eb6f3423e..d5e9d6721bce626 100644 --- a/tests/net/socket/tls/src/main.c +++ b/tests/net/socket/tls/src/main.c @@ -809,6 +809,10 @@ static void fake_tcp_server_work(struct k_work *work) test_accept(data->sock, &new_sock, NULL, 0); if (!data->reply) { + /* Add small delay to avoid race between incoming data and + * sending FIN. + */ + k_msleep(10); goto out; } diff --git a/tests/net/tcp/prj.conf b/tests/net/tcp/prj.conf index 86f972f043dd4c3..2e67a55dd1bc114 100644 --- a/tests/net/tcp/prj.conf +++ b/tests/net/tcp/prj.conf @@ -29,6 +29,7 @@ CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 CONFIG_NET_TCP_CHECKSUM=n CONFIG_NET_TCP_RANDOMIZED_RTO=n CONFIG_NET_TCP_INIT_RETRANSMISSION_TIMEOUT=100 +CONFIG_NET_TCP_RETRY_COUNT=2 CONFIG_NET_IPV6_ND=n CONFIG_NET_IPV6_DAD=n diff --git a/tests/net/tcp/src/main.c b/tests/net/tcp/src/main.c index e935cb4d40e5e14..547fd4fc133cd4d 100644 --- a/tests/net/tcp/src/main.c +++ b/tests/net/tcp/src/main.c @@ -127,7 +127,9 @@ static void handle_server_test(sa_family_t af, struct tcphdr *th); static void handle_syn_resend(void); static void handle_syn_rst_ack(sa_family_t af, struct tcphdr *th); static void handle_client_fin_wait_2_test(sa_family_t af, struct tcphdr *th); +static void handle_client_fin_wait_2_failure_test(sa_family_t af, struct tcphdr *th); static void handle_client_closing_test(sa_family_t af, struct tcphdr *th); +static void handle_client_closing_failure_test(sa_family_t af, struct tcphdr *th); static void handle_data_fin1_test(sa_family_t af, struct tcphdr *th); static void handle_data_during_fin1_test(sa_family_t af, struct tcphdr *th); static void handle_server_recv_out_of_order(struct net_pkt *pkt); @@ -215,6 +217,15 @@ static void test_sem_take(k_timeout_t timeout, int line) } } +static void test_sem_take_failure(k_timeout_t timeout, int line) +{ + sem = true; + + if (k_sem_take(&test_sem, timeout) == 0) { + zassert_true(false, "semaphore succeed out (line %d)", line); + } +} + static uint8_t tcp_options[20] = { 0x02, 0x04, 0x05, 0xb4, /* Max segment */ 0x04, 0x02, /* SACK */ @@ -468,6 +479,12 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt) case 15: handle_syn_invalid_ack(net_pkt_family(pkt), &th); break; + case 16: + handle_client_closing_failure_test(net_pkt_family(pkt), &th); + break; + case 17: + handle_client_fin_wait_2_failure_test(net_pkt_family(pkt), &th); + break; default: zassert_true(false, "Undefined test case"); @@ -1230,6 +1247,147 @@ ZTEST(net_tcp, test_client_fin_wait_2_ipv4) k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY)); } +static void handle_client_fin_wait_2_failure_test(sa_family_t af, struct tcphdr *th) +{ + struct net_pkt *reply; + int ret; + +send_next: + switch (t_state) { + case T_SYN: + test_verify_flags(th, SYN); + seq = 0U; + ack = ntohl(th->th_seq) + 1U; + reply = prepare_syn_ack_packet(af, htons(MY_PORT), + th->th_sport); + t_state = T_SYN_ACK; + break; + case T_SYN_ACK: + test_verify_flags(th, ACK); + /* connection is success */ + t_state = T_DATA; + test_sem_give(); + return; + case T_DATA: + test_verify_flags(th, PSH | ACK); + seq++; + ack = ack + 1U; + reply = prepare_ack_packet(af, htons(MY_PORT), th->th_sport); + t_state = T_FIN; + test_sem_give(); + break; + case T_FIN: + test_verify_flags(th, FIN | ACK); + ack = ack + 1U; + t_state = T_FIN_2; + reply = prepare_ack_packet(af, htons(MY_PORT), th->th_sport); + break; + case T_FIN_2: + t_state = T_FIN_ACK; + /* We do not send last FIN that would move the state to TIME_WAIT. + * Make sure that the stack can recover from this by closing the + * connection. + */ + reply = NULL; + break; + case T_FIN_ACK: + reply = NULL; + return; + default: + zassert_true(false, "%s unexpected state", __func__); + return; + } + + if (reply != NULL) { + ret = net_recv_data(net_iface, reply); + if (ret < 0) { + goto fail; + } + } + + if (t_state == T_FIN_2) { + goto send_next; + } + + return; +fail: + zassert_true(false, "%s failed", __func__); +} + +static bool closed; +static K_SEM_DEFINE(wait_data, 0, 1); + +static void connection_closed(struct tcp *conn, void *user_data) +{ + struct k_sem *my_sem = user_data; + + k_sem_give(my_sem); + closed = true; +} + +/* Test case scenario IPv4 + * send SYN, + * expect SYN ACK, + * send ACK, + * send Data, + * expect ACK, + * send FIN, + * expect ACK, + * expect FIN, + * send ACK, + * any failures cause test case to fail. + */ +ZTEST(net_tcp, test_client_fin_wait_2_ipv4_failure) +{ + struct net_context *ctx; + uint8_t data = 0x41; /* "A" */ + int ret; + + t_state = T_SYN; + test_case_no = 17; + seq = ack = 0; + closed = false; + + ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ctx); + if (ret < 0) { + zassert_true(false, "Failed to get net_context"); + } + + net_context_ref(ctx); + + ret = net_context_connect(ctx, (struct sockaddr *)&peer_addr_s, + sizeof(struct sockaddr_in), + NULL, + K_MSEC(100), NULL); + if (ret < 0) { + zassert_true(false, "Failed to connect to peer"); + } + + /* Peer will release the semaphore after it receives + * proper ACK to SYN | ACK + */ + test_sem_take(K_MSEC(100), __LINE__); + + ret = net_context_send(ctx, &data, 1, NULL, K_NO_WAIT, NULL); + if (ret < 0) { + zassert_true(false, "Failed to send data to peer"); + } + + /* Peer will release the semaphore after it sends ACK for data */ + test_sem_take(K_MSEC(100), __LINE__); + + k_sem_reset(&wait_data); + k_sem_take(&wait_data, K_NO_WAIT); + + tcp_install_close_cb(ctx, connection_closed, &wait_data); + + net_context_put(ctx); + + /* The lock is released after we have closed the connection. */ + k_sem_take(&wait_data, K_MSEC(10000)); + zassert_equal(closed, true, "Connection was not closed!"); +} + static uint32_t get_rel_seq(struct tcphdr *th) { return ntohl(th->th_seq) - device_initial_seq; @@ -1614,6 +1772,126 @@ ZTEST(net_tcp, test_client_closing_ipv6) k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY)); } +/* In this test we check that things work properly if we do not receive + * the final ACK that leads to TIME_WAIT state. + */ +static void handle_client_closing_failure_test(sa_family_t af, struct tcphdr *th) +{ + struct net_pkt *reply; + int ret; + + switch (t_state) { + case T_SYN: + test_verify_flags(th, SYN); + seq = 0U; + ack = ntohl(th->th_seq) + 1U; + reply = prepare_syn_ack_packet(af, htons(MY_PORT), + th->th_sport); + t_state = T_SYN_ACK; + break; + case T_SYN_ACK: + test_verify_flags(th, ACK); + /* connection is success */ + t_state = T_DATA; + test_sem_give(); + return; + case T_DATA: + test_verify_flags(th, PSH | ACK); + seq++; + ack = ack + 1U; + reply = prepare_ack_packet(af, htons(MY_PORT), th->th_sport); + t_state = T_FIN; + test_sem_give(); + break; + case T_FIN: + test_verify_flags(th, FIN | ACK); + t_state = T_FIN_1; + reply = prepare_fin_packet(af, htons(MY_PORT), th->th_sport); + break; + case T_FIN_1: + test_verify_flags(th, FIN | ACK); + t_state = T_CLOSING; + reply = prepare_fin_packet(af, htons(MY_PORT), th->th_sport); + break; + case T_CLOSING: + test_verify_flags(th, FIN | ACK); + /* Simulate the case where we do not receive final ACK */ + reply = NULL; + break; + default: + zassert_true(false, "%s unexpected state", __func__); + return; + } + + if (reply != NULL) { + ret = net_recv_data(net_iface, reply); + if (ret < 0) { + goto fail; + } + } + + return; +fail: + zassert_true(false, "%s failed", __func__); +} + +/* Test case scenario IPv6 + * send SYN, + * expect SYN ACK, + * send ACK, + * send Data, + * expect ACK, + * send FIN, + * expect FIN, + * send ACK, + * expect ACK but fail to receive it + * any failures cause test case to fail. + */ +ZTEST(net_tcp, test_client_closing_failure_ipv6) +{ + struct net_context *ctx; + uint8_t data = 0x41; /* "A" */ + int ret; + + t_state = T_SYN; + test_case_no = 16; + seq = ack = 0; + + ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &ctx); + if (ret < 0) { + zassert_true(false, "Failed to get net_context"); + } + + net_context_ref(ctx); + + ret = net_context_connect(ctx, (struct sockaddr *)&peer_addr_v6_s, + sizeof(struct sockaddr_in6), + NULL, + K_MSEC(100), NULL); + if (ret < 0) { + zassert_true(false, "Failed to connect to peer"); + } + + /* Peer will release the semaphore after it receives + * proper ACK to SYN | ACK + */ + test_sem_take(K_MSEC(100), __LINE__); + + ret = net_context_send(ctx, &data, 1, NULL, K_NO_WAIT, NULL); + if (ret < 0) { + zassert_true(false, "Failed to send data to peer"); + } + + /* Peer will release the semaphore after it sends ACK for data */ + test_sem_take(K_MSEC(100), __LINE__); + + net_context_put(ctx); + + /* The lock is not released as we do not receive final ACK. + */ + test_sem_take_failure(K_MSEC(400), __LINE__); +} + static struct net_context *create_server_socket(uint32_t my_seq, uint32_t my_ack) { diff --git a/tests/posix/common/src/clock.c b/tests/posix/common/src/clock.c index 3677e606c16c9f9..21319bf3592e6ff 100644 --- a/tests/posix/common/src/clock.c +++ b/tests/posix/common/src/clock.c @@ -213,3 +213,15 @@ ZTEST(posix_apis, test_realtime) CONFIG_TEST_CLOCK_RT_ERROR_MS, lo_wm, cma, hi_wm); zassert_between_inclusive(cma, lo, hi); } + +ZTEST(posix_apis, test_clock_getcpuclockid) +{ + int ret = 0; + clockid_t clock_id; + + ret = clock_getcpuclockid((pid_t)0, &clock_id); + zassert_equal(ret, 0, "POSIX clock_getcpuclock id failed"); + + ret = clock_getcpuclockid((pid_t)2482, &clock_id); + zassert_equal(ret, EPERM, "POSIX clock_getcpuclock id failed"); +} diff --git a/tests/posix/common/src/key.c b/tests/posix/common/src/key.c index 58e67a313acb7c9..dbeddc3b6d0e61f 100644 --- a/tests/posix/common/src/key.c +++ b/tests/posix/common/src/key.c @@ -10,102 +10,54 @@ #include #define N_THR 2 -#define N_KEY 2 -#define STACKSZ (MAX(1024, PTHREAD_STACK_MIN) + CONFIG_TEST_EXTRA_STACK_SIZE) +#define N_KEY 2 #define BUFFSZ 48 -K_THREAD_STACK_ARRAY_DEFINE(stackp, N_THR, STACKSZ); - -pthread_key_t key, keys[N_KEY]; +static pthread_key_t key; +static pthread_key_t keys[N_KEY]; static pthread_once_t key_once = PTHREAD_ONCE_INIT; static pthread_once_t keys_once = PTHREAD_ONCE_INIT; -void *thread_top(void *p1) +static void *thread_top(void *p1) { - int ret = -1; - void *value; - void *getval; char *buffer[BUFFSZ]; value = k_malloc(sizeof(buffer)); - - zassert_true((int) POINTER_TO_INT(value), - "thread could not allocate storage"); - - ret = pthread_setspecific(key, value); - - /* TESTPOINT: Check if thread's value is associated with key */ - zassert_false(ret, "pthread_setspecific failed"); - - getval = 0; - - getval = pthread_getspecific(key); - - /* TESTPOINT: Check if pthread_getspecific returns the same value - * set by pthread_setspecific - */ - zassert_equal(value, getval, - "set and retrieved values are different"); - - printk("set value = %d and retrieved value = %d\n", - (int) POINTER_TO_INT(value), (int) POINTER_TO_INT(getval)); + zassert_not_null(value, "thread could not allocate storage"); + zassert_ok(pthread_setspecific(key, value), "pthread_setspecific failed"); + zassert_equal(pthread_getspecific(key), value, "set and retrieved values are different"); + k_free(value); return NULL; } -void *thread_func(void *p1) +static void *thread_func(void *p1) { - int i, ret = -1; - void *value; - void *getval; char *buffer[BUFFSZ]; value = k_malloc(sizeof(buffer)); - - zassert_true((int) POINTER_TO_INT(value), - "thread could not allocate storage"); - - for (i = 0; i < N_KEY; i++) { - ret = pthread_setspecific(keys[i], value); - - /* TESTPOINT: Check if thread's value is associated with keys */ - zassert_false(ret, "pthread_setspecific failed"); - } - - for (i = 0; i < N_KEY; i++) { - getval = 0; - getval = pthread_getspecific(keys[i]); - - /* TESTPOINT: Check if pthread_getspecific returns the same - * value set by pthread_setspecific for each of the keys - */ - zassert_equal(value, getval, - "set and retrieved values are different"); - - printk("key %d: set value = %d and retrieved value = %d\n", - i, (int) POINTER_TO_INT(value), - (int) POINTER_TO_INT(getval)); + zassert_not_null(value, "thread could not allocate storage"); + for (int i = 0; i < N_KEY; i++) { + zassert_ok(pthread_setspecific(keys[i], value), "pthread_setspecific failed"); + zassert_equal(pthread_getspecific(keys[i]), value, + "set and retrieved values are different"); } + k_free(value); return NULL; } static void make_key(void) { - int ret = 0; - - ret = pthread_key_create(&key, NULL); - zassert_false(ret, "insufficient memory to create key"); + zassert_ok(pthread_key_create(&key, NULL), "insufficient memory to create key"); } static void make_keys(void) { - int i, ret = 0; - - for (i = 0; i < N_KEY; i++) { - ret = pthread_key_create(&keys[i], NULL); - zassert_false(ret, "insufficient memory to create keys"); + for (int i = 0; i < N_KEY; i++) { + zassert_ok(pthread_key_create(&keys[i], NULL), + "insufficient memory to create keys"); } } @@ -124,94 +76,41 @@ static void make_keys(void) ZTEST(posix_apis, test_key_1toN_thread) { - int i, ret = -1; - - pthread_attr_t attr[N_THR]; - struct sched_param schedparam; - pthread_t newthread[N_THR]; void *retval; + pthread_t newthread[N_THR]; - ret = pthread_once(&key_once, make_key); - - /* TESTPOINT: Check if key is created */ - zassert_false(ret, "attempt to create key failed"); - - printk("\nDifferent threads set different values to same key:\n"); - - /* Creating threads with lowest application priority */ - for (i = 0; i < N_THR; i++) { - ret = pthread_attr_init(&attr[i]); - if (ret != 0) { - zassert_false(pthread_attr_destroy(&attr[i]), - "Unable to destroy pthread object attr"); - zassert_false(pthread_attr_init(&attr[i]), - "Unable to create pthread object attr"); - } - - schedparam.sched_priority = 2; - pthread_attr_setschedparam(&attr[i], &schedparam); - pthread_attr_setstack(&attr[i], &stackp[i][0], STACKSZ); + zassert_ok(pthread_once(&key_once, make_key), "attempt to create key failed"); - ret = pthread_create(&newthread[i], &attr[i], thread_top, - INT_TO_POINTER(i)); + /* Different threads set different values to same key */ - /* TESTPOINT: Check if threads are created successfully */ - zassert_false(ret, "attempt to create threads failed"); + for (int i = 0; i < N_THR; i++) { + zassert_ok(pthread_create(&newthread[i], NULL, thread_top, NULL), + "attempt to create thread %d failed", i); } - for (i = 0; i < N_THR; i++) { - printk("thread %d: ", i); - pthread_join(newthread[i], &retval); + for (int i = 0; i < N_THR; i++) { + zassert_ok(pthread_join(newthread[i], &retval), "failed to join thread %d", i); } - ret = pthread_key_delete(key); - - /* TESTPOINT: Check if key is deleted */ - zassert_false(ret, "attempt to delete key failed"); - printk("\n"); + zassert_ok(pthread_key_delete(key), "attempt to delete key failed"); } ZTEST(posix_apis, test_key_Nto1_thread) { - int i, ret = -1; - - pthread_attr_t attr; - struct sched_param schedparam; pthread_t newthread; - ret = pthread_once(&keys_once, make_keys); - - /* TESTPOINT: Check if keys are created successfully */ - zassert_false(ret, "attempt to create keys failed"); - - printk("\nSingle thread associates its value with different keys:\n"); - ret = pthread_attr_init(&attr); - if (ret != 0) { - zassert_false(pthread_attr_destroy(&attr), - "Unable to destroy pthread object attr"); - zassert_false(pthread_attr_init(&attr), - "Unable to create pthread object attr"); - } - - schedparam.sched_priority = 2; - pthread_attr_setschedparam(&attr, &schedparam); - pthread_attr_setstack(&attr, &stackp[0][0], STACKSZ); - - ret = pthread_create(&newthread, &attr, thread_func, - (void *)0); + zassert_ok(pthread_once(&keys_once, make_keys), "attempt to create keys failed"); - /*TESTPOINT: Check if thread is created successfully */ - zassert_false(ret, "attempt to create thread failed"); + /* Single thread associates its value with different keys */ - pthread_join(newthread, NULL); + zassert_ok(pthread_create(&newthread, NULL, thread_func, NULL), + "attempt to create thread failed"); - for (i = 0; i < N_KEY; i++) { - ret = pthread_key_delete(keys[i]); + zassert_ok(pthread_join(newthread, NULL), "failed to join thread"); - /* TESTPOINT: Check if keys are deleted */ - zassert_false(ret, "attempt to delete keys failed"); + for (int i = 0; i < N_KEY; i++) { + zassert_ok(pthread_key_delete(keys[i]), "attempt to delete keys[%d] failed", i); } - printk("\n"); } ZTEST(posix_apis, test_key_resource_leak) diff --git a/tests/posix/common/src/mqueue.c b/tests/posix/common/src/mqueue.c index 65df6fbe777210d..4ddfdea2da9a86a 100644 --- a/tests/posix/common/src/mqueue.c +++ b/tests/posix/common/src/mqueue.c @@ -11,15 +11,12 @@ #include #include -#define N_THR 2 -#define STACKSZ (MAX(1024, PTHREAD_STACK_MIN) + CONFIG_TEST_EXTRA_STACK_SIZE) +#define N_THR 2 #define SENDER_THREAD 0 #define RECEIVER_THREAD 1 #define MESSAGE_SIZE 16 #define MESG_COUNT_PERMQ 4 -K_THREAD_STACK_ARRAY_DEFINE(stacks, N_THR, STACKSZ); - char queue[16] = "server"; char send_data[MESSAGE_SIZE] = "timed data send"; @@ -60,7 +57,8 @@ void *receiver_thread(void *p1) clock_gettime(CLOCK_MONOTONIC, &curtime); curtime.tv_sec += 1; mq_timedreceive(mqd, rec_data, MESSAGE_SIZE, 0, &curtime); - zassert_false(strcmp(rec_data, send_data), "Error in data reception"); + zassert_false(strcmp(rec_data, send_data), "Error in data reception. exp: %s act: %s", + send_data, rec_data); usleep(USEC_PER_MSEC); zassert_false(mq_close(mqd), "unable to close message queue descriptor."); @@ -72,9 +70,9 @@ ZTEST(posix_apis, test_mqueue) { mqd_t mqd; struct mq_attr attrs; - int32_t mode = 0777, flags = O_RDWR | O_CREAT, ret, i; + int32_t mode = 0777; + int flags = O_RDWR | O_CREAT; void *retval; - pthread_attr_t attr[N_THR]; pthread_t newthread[N_THR]; attrs.mq_msgsize = MESSAGE_SIZE; @@ -82,28 +80,15 @@ ZTEST(posix_apis, test_mqueue) mqd = mq_open(queue, flags, mode, &attrs); - for (i = 0; i < N_THR; i++) { + for (int i = 0; i < N_THR; i++) { /* Creating threads */ - zassert_ok(pthread_attr_init(&attr[i])); - pthread_attr_setstack(&attr[i], &stacks[i][0], STACKSZ); - - if (i % 2) { - ret = pthread_create(&newthread[i], &attr[i], - sender_thread, - INT_TO_POINTER(i)); - } else { - ret = pthread_create(&newthread[i], &attr[i], - receiver_thread, - INT_TO_POINTER(i)); - } - - zassert_false(ret, "Not enough space to create new thread"); - zassert_equal(pthread_attr_destroy(&attr[i]), 0); + zassert_ok(pthread_create(&newthread[i], NULL, + (i % 2 == 0) ? receiver_thread : sender_thread, NULL)); } usleep(USEC_PER_MSEC * 10U); - for (i = 0; i < N_THR; i++) { + for (int i = 0; i < N_THR; i++) { pthread_join(newthread[i], &retval); } diff --git a/tests/posix/common/src/mutex.c b/tests/posix/common/src/mutex.c index 6a63f98e4510a30..ded1055f7dceec6 100644 --- a/tests/posix/common/src/mutex.c +++ b/tests/posix/common/src/mutex.c @@ -10,14 +10,8 @@ #include #include -#define STACK_SIZE (MAX(1024, PTHREAD_STACK_MIN) + CONFIG_TEST_EXTRA_STACK_SIZE) - -static K_THREAD_STACK_DEFINE(stack, STACK_SIZE); - #define SLEEP_MS 100 -pthread_mutex_t mutex1; -pthread_mutex_t mutex2; pthread_mutex_t mutex; void *normal_mutex_entry(void *p1) @@ -27,7 +21,7 @@ void *normal_mutex_entry(void *p1) /* Sleep for maximum 300 ms as main thread is sleeping for 100 ms */ for (i = 0; i < 3; i++) { - rc = pthread_mutex_trylock(&mutex1); + rc = pthread_mutex_trylock(&mutex); if (rc == 0) { break; } @@ -36,74 +30,62 @@ void *normal_mutex_entry(void *p1) zassert_false(rc, "try lock failed"); TC_PRINT("mutex lock is taken\n"); - zassert_false(pthread_mutex_unlock(&mutex1), "mutex unlock is failed"); + zassert_false(pthread_mutex_unlock(&mutex), "mutex unlock is failed"); return NULL; } void *recursive_mutex_entry(void *p1) { - zassert_false(pthread_mutex_lock(&mutex2), "mutex is not taken"); - zassert_false(pthread_mutex_lock(&mutex2), "mutex is not taken 2nd time"); + zassert_false(pthread_mutex_lock(&mutex), "mutex is not taken"); + zassert_false(pthread_mutex_lock(&mutex), "mutex is not taken 2nd time"); TC_PRINT("recursive mutex lock is taken\n"); - zassert_false(pthread_mutex_unlock(&mutex2), "mutex is not unlocked"); - zassert_false(pthread_mutex_unlock(&mutex2), "mutex is not unlocked"); + zassert_false(pthread_mutex_unlock(&mutex), "mutex is not unlocked"); + zassert_false(pthread_mutex_unlock(&mutex), "mutex is not unlocked"); return NULL; } -/** - * @brief Test to demonstrate PTHREAD_MUTEX_NORMAL - * - * @details Mutex type is setup as normal. pthread_mutex_trylock - * and pthread_mutex_lock are tested with mutex type being - * normal. - */ -ZTEST(posix_apis, test_mutex_normal) +static void test_mutex_common(int type, void *(*entry)(void *arg)) { - pthread_t thread_1; - pthread_attr_t attr; - pthread_mutexattr_t mut_attr; + pthread_t th; + int protocol; + int actual_type; struct sched_param schedparam; - int schedpolicy = SCHED_FIFO; - int ret, type, protocol, temp; + pthread_mutexattr_t mut_attr = {0}; schedparam.sched_priority = 2; - ret = pthread_attr_init(&attr); - if (ret != 0) { - zassert_false(pthread_attr_destroy(&attr), - "Unable to destroy pthread object attrib"); - zassert_false(pthread_attr_init(&attr), "Unable to create pthread object attrib"); - } - - pthread_attr_setstack(&attr, &stack, STACK_SIZE); - pthread_attr_setschedpolicy(&attr, schedpolicy); - pthread_attr_setschedparam(&attr, &schedparam); - temp = pthread_mutexattr_settype(&mut_attr, PTHREAD_MUTEX_NORMAL); - zassert_false(temp, "setting mutex type is failed"); - temp = pthread_mutex_init(&mutex1, &mut_attr); - zassert_false(temp, "mutex initialization is failed"); + zassert_ok(pthread_mutexattr_settype(&mut_attr, type), "setting mutex type is failed"); + zassert_ok(pthread_mutex_init(&mutex, &mut_attr), "mutex initialization is failed"); - temp = pthread_mutexattr_gettype(&mut_attr, &type); - zassert_false(temp, "reading mutex type is failed"); - temp = pthread_mutexattr_getprotocol(&mut_attr, &protocol); - zassert_false(temp, "reading mutex protocol is failed"); + zassert_ok(pthread_mutexattr_gettype(&mut_attr, &actual_type), + "reading mutex type is failed"); + zassert_ok(pthread_mutexattr_getprotocol(&mut_attr, &protocol), + "reading mutex protocol is failed"); - pthread_mutex_lock(&mutex1); - - zassert_equal(type, PTHREAD_MUTEX_NORMAL, "mutex type is not normal"); + zassert_ok(pthread_mutex_lock(&mutex)); + zassert_equal(actual_type, type, "mutex type is not normal"); zassert_equal(protocol, PTHREAD_PRIO_NONE, "mutex protocol is not prio_none"); - ret = pthread_create(&thread_1, &attr, &normal_mutex_entry, NULL); - if (ret) { - TC_PRINT("Thread1 creation failed %d", ret); - } + zassert_ok(pthread_create(&th, NULL, entry, NULL)); + k_msleep(SLEEP_MS); - pthread_mutex_unlock(&mutex1); + zassert_ok(pthread_mutex_unlock(&mutex)); + + zassert_ok(pthread_join(th, NULL)); + zassert_ok(pthread_mutex_destroy(&mutex), "Destroying mutex is failed"); +} - pthread_join(thread_1, NULL); - temp = pthread_mutex_destroy(&mutex1); - zassert_false(temp, "Destroying mutex is failed"); +/** + * @brief Test to demonstrate PTHREAD_MUTEX_NORMAL + * + * @details Mutex type is setup as normal. pthread_mutex_trylock + * and pthread_mutex_lock are tested with mutex type being + * normal. + */ +ZTEST(posix_apis, test_mutex_normal) +{ + test_mutex_common(PTHREAD_MUTEX_NORMAL, normal_mutex_entry); } /** @@ -115,45 +97,7 @@ ZTEST(posix_apis, test_mutex_normal) */ ZTEST(posix_apis, test_mutex_recursive) { - pthread_t thread_2; - pthread_attr_t attr2; - pthread_mutexattr_t mut_attr2; - struct sched_param schedparam2; - int schedpolicy = SCHED_FIFO; - int ret, type, protocol, temp; - - schedparam2.sched_priority = 2; - ret = pthread_attr_init(&attr2); - if (ret != 0) { - zassert_false(pthread_attr_destroy(&attr2), - "Unable to destroy pthread object attrib"); - zassert_false(pthread_attr_init(&attr2), "Unable to create pthread object attrib"); - } - - pthread_attr_setstack(&attr2, &stack, STACK_SIZE); - pthread_attr_setschedpolicy(&attr2, schedpolicy); - pthread_attr_setschedparam(&attr2, &schedparam2); - - temp = pthread_mutexattr_settype(&mut_attr2, PTHREAD_MUTEX_RECURSIVE); - zassert_false(temp, "setting mutex2 type is failed"); - temp = pthread_mutex_init(&mutex2, &mut_attr2); - zassert_false(temp, "mutex2 initialization is failed"); - - temp = pthread_mutexattr_gettype(&mut_attr2, &type); - zassert_false(temp, "reading mutex2 type is failed"); - temp = pthread_mutexattr_getprotocol(&mut_attr2, &protocol); - zassert_false(temp, "reading mutex2 protocol is failed"); - - zassert_equal(type, PTHREAD_MUTEX_RECURSIVE, "mutex2 type is not recursive"); - - zassert_equal(protocol, PTHREAD_PRIO_NONE, "mutex2 protocol is not prio_none"); - ret = pthread_create(&thread_2, &attr2, &recursive_mutex_entry, NULL); - - zassert_false(ret, "Thread2 creation failed"); - - pthread_join(thread_2, NULL); - temp = pthread_mutex_destroy(&mutex2); - zassert_false(temp, "Destroying mutex2 is failed"); + test_mutex_common(PTHREAD_MUTEX_RECURSIVE, recursive_mutex_entry); } /** @@ -228,23 +172,19 @@ ZTEST(posix_apis, test_mutex_timedlock) { void *ret; pthread_t th; - pthread_attr_t attr; - - zassert_ok(pthread_attr_init(&attr)); - zassert_ok(pthread_attr_setstack(&attr, &stack, STACK_SIZE)); zassert_ok(pthread_mutex_init(&mutex, NULL)); printk("Expecting timedlock with timeout of %d ms to fail\n", TIMEDLOCK_TIMEOUT_MS); zassert_ok(pthread_mutex_lock(&mutex)); - zassert_ok(pthread_create(&th, &attr, test_mutex_timedlock_fn, &mutex)); + zassert_ok(pthread_create(&th, NULL, test_mutex_timedlock_fn, &mutex)); zassert_ok(pthread_join(th, &ret)); /* ensure timeout occurs */ zassert_equal(ETIMEDOUT, POINTER_TO_INT(ret)); printk("Expecting timedlock with timeout of %d ms to succeed after 100ms\n", TIMEDLOCK_TIMEOUT_MS); - zassert_ok(pthread_create(&th, &attr, test_mutex_timedlock_fn, &mutex)); + zassert_ok(pthread_create(&th, NULL, test_mutex_timedlock_fn, &mutex)); /* unlock before timeout expires */ k_msleep(TIMEDLOCK_TIMEOUT_DELAY_MS); zassert_ok(pthread_mutex_unlock(&mutex)); @@ -253,5 +193,4 @@ ZTEST(posix_apis, test_mutex_timedlock) zassert_ok(POINTER_TO_INT(ret)); zassert_ok(pthread_mutex_destroy(&mutex)); - zassert_ok(pthread_attr_destroy(&attr)); } diff --git a/tests/posix/common/src/pthread.c b/tests/posix/common/src/pthread.c index 16c4af2e3602c59..7cf2405c2b44092 100644 --- a/tests/posix/common/src/pthread.c +++ b/tests/posix/common/src/pthread.c @@ -710,7 +710,7 @@ ZTEST(posix_apis, test_sched_policy) } /* get pmin and pmax for policies[policy] */ - for (int i = 0; i < 2; ++i) { + for (int i = 0; i < ARRAY_SIZE(prios); ++i) { errno = 0; if (i == 0) { pmin = sched_get_priority_min(policies[policy]); @@ -749,7 +749,7 @@ ZTEST(posix_apis, test_sched_policy) zassert_equal(pmax, nprio[policy] - 1, "unexpected pmax for %s", policy_names[policy]); /* test happy paths */ - for (int i = 0; i < 2; ++i) { + for (int i = 0; i < ARRAY_SIZE(prios); ++i) { /* create threads with min and max priority levels */ zassert_ok(pthread_attr_init(&attr), "pthread_attr_init() failed for %s (%d) of %s", prios[i], @@ -774,6 +774,10 @@ ZTEST(posix_apis, test_sched_policy) zassert_ok(pthread_join(th, NULL), "pthread_join() failed for %s (%d) of %s", prios[i], param.sched_priority, policy_names[policy]); + + zassert_ok(pthread_attr_destroy(&attr), + "pthread_attr_destroy() failed for %s (%d) of %s", prios[i], + param.sched_priority, policy_names[policy]); } } } @@ -845,12 +849,8 @@ ZTEST(posix_apis, test_pthread_return_val) { pthread_t pth; void *ret = NULL; - pthread_attr_t attr; - - zassert_ok(pthread_attr_init(&attr)); - zassert_ok(pthread_attr_setstack(&attr, &stack_e[0][0], STACKS)); - zassert_ok(pthread_create(&pth, &attr, non_null_retval, NULL)); + zassert_ok(pthread_create(&pth, NULL, non_null_retval, NULL)); zassert_ok(pthread_join(pth, &ret)); zassert_equal(ret, (void *)BIOS_FOOD); } @@ -865,12 +865,8 @@ static void *detached(void *arg) ZTEST(posix_apis, test_pthread_join_detached) { pthread_t pth; - pthread_attr_t attr; - - zassert_ok(pthread_attr_init(&attr)); - zassert_ok(pthread_attr_setstack(&attr, &stack_e[0][0], STACKS)); - zassert_ok(pthread_create(&pth, &attr, detached, NULL)); + zassert_ok(pthread_create(&pth, NULL, detached, NULL)); zassert_ok(pthread_detach(pth)); /* note, this was required to be EINVAL previously but is now undefined behaviour */ zassert_not_equal(0, pthread_join(pth, NULL)); diff --git a/tests/posix/common/src/rwlock.c b/tests/posix/common/src/rwlock.c index 43c573a70075de3..b7d3ac2abe21fc5 100644 --- a/tests/posix/common/src/rwlock.c +++ b/tests/posix/common/src/rwlock.c @@ -6,59 +6,50 @@ #include +#include #include #include #define N_THR 3 -#define STACKSZ (MAX(1024, PTHREAD_STACK_MIN) + CONFIG_TEST_EXTRA_STACK_SIZE) -K_THREAD_STACK_ARRAY_DEFINE(stack, N_THR, STACKSZ); -pthread_rwlock_t rwlock; +LOG_MODULE_REGISTER(posix_rwlock_test); + +static pthread_rwlock_t rwlock; static void *thread_top(void *p1) { - pthread_t pthread; - uint32_t policy, ret = 0U; - struct sched_param param; - int id = POINTER_TO_INT(p1); - - pthread = (pthread_t) pthread_self(); - pthread_getschedparam(pthread, &policy, ¶m); - printk("Thread %d scheduling policy = %d & priority %d started\n", - id, policy, param.sched_priority); + int ret; + pthread_t id; + id = (pthread_t)pthread_self(); ret = pthread_rwlock_tryrdlock(&rwlock); - if (ret) { - printk("Not able to get RD lock on trying, try again\n"); - zassert_false(pthread_rwlock_rdlock(&rwlock), - "Failed to acquire write lock"); + if (ret != 0) { + LOG_DBG("Not able to get RD lock on trying, try again"); + zassert_ok(pthread_rwlock_rdlock(&rwlock), "Failed to acquire write lock"); } - printk("Thread %d got RD lock\n", id); + LOG_DBG("Thread %d got RD lock", id); usleep(USEC_PER_MSEC); - printk("Thread %d releasing RD lock\n", id); - zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); + LOG_DBG("Thread %d releasing RD lock", id); + zassert_ok(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); - printk("Thread %d acquiring WR lock\n", id); + LOG_DBG("Thread %d acquiring WR lock", id); ret = pthread_rwlock_trywrlock(&rwlock); - if (ret != 0U) { - zassert_false(pthread_rwlock_wrlock(&rwlock), - "Failed to acquire WR lock"); + if (ret != 0) { + zassert_ok(pthread_rwlock_wrlock(&rwlock), "Failed to acquire WR lock"); } - printk("Thread %d acquired WR lock\n", id); + LOG_DBG("Thread %d acquired WR lock", id); usleep(USEC_PER_MSEC); - printk("Thread %d releasing WR lock\n", id); - zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); - pthread_exit(NULL); + LOG_DBG("Thread %d releasing WR lock", id); + zassert_ok(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); + return NULL; } ZTEST(posix_apis, test_rw_lock) { - int32_t i, ret; - pthread_attr_t attr[N_THR]; - struct sched_param schedparam; + int ret; pthread_t newthread[N_THR]; struct timespec time; void *status; @@ -75,72 +66,53 @@ ZTEST(posix_apis, test_rw_lock) zassert_equal(pthread_rwlock_timedrdlock(&rwlock, &time), EINVAL); zassert_equal(pthread_rwlock_unlock(&rwlock), EINVAL); - zassert_false(pthread_rwlock_init(&rwlock, NULL), - "Failed to create rwlock"); - printk("\nmain acquire WR lock and 3 threads acquire RD lock\n"); - zassert_false(pthread_rwlock_timedwrlock(&rwlock, &time), - "Failed to acquire write lock"); + zassert_ok(pthread_rwlock_init(&rwlock, NULL), "Failed to create rwlock"); + LOG_DBG("main acquire WR lock and 3 threads acquire RD lock"); + zassert_ok(pthread_rwlock_timedwrlock(&rwlock, &time), "Failed to acquire write lock"); /* Creating N preemptive threads in increasing order of priority */ - for (i = 0; i < N_THR; i++) { - zassert_equal(pthread_attr_init(&attr[i]), 0, - "Unable to create pthread object attrib"); - - /* Setting scheduling priority */ - schedparam.sched_priority = i + 1; - pthread_attr_setschedparam(&attr[i], &schedparam); - - /* Setting stack */ - pthread_attr_setstack(&attr[i], &stack[i][0], STACKSZ); - - ret = pthread_create(&newthread[i], &attr[i], thread_top, - INT_TO_POINTER(i)); - zassert_false(ret, "Low memory to thread new thread"); - + for (int i = 0; i < N_THR; i++) { + zassert_ok(pthread_create(&newthread[i], NULL, thread_top, NULL), + "Low memory to thread new thread"); } /* Delay to give change to child threads to run */ usleep(USEC_PER_MSEC); - printk("Parent thread releasing WR lock\n"); - zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); + LOG_DBG("Parent thread releasing WR lock"); + zassert_ok(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); /* Let child threads acquire RD Lock */ usleep(USEC_PER_MSEC); - printk("Parent thread acquiring WR lock again\n"); + LOG_DBG("Parent thread acquiring WR lock again"); time.tv_sec = 2; time.tv_nsec = 0; ret = pthread_rwlock_timedwrlock(&rwlock, &time); - if (ret) { - zassert_false(pthread_rwlock_wrlock(&rwlock), - "Failed to acquire write lock"); + zassert_ok(pthread_rwlock_wrlock(&rwlock), "Failed to acquire write lock"); } - printk("Parent thread acquired WR lock again\n"); + LOG_DBG("Parent thread acquired WR lock again"); usleep(USEC_PER_MSEC); - printk("Parent thread releasing WR lock again\n"); - zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); + LOG_DBG("Parent thread releasing WR lock again"); + zassert_ok(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); - printk("\n3 threads acquire WR lock\n"); - printk("Main thread acquiring RD lock\n"); + LOG_DBG("3 threads acquire WR lock"); + LOG_DBG("Main thread acquiring RD lock"); ret = pthread_rwlock_timedrdlock(&rwlock, &time); - if (ret != 0) { - zassert_false(pthread_rwlock_rdlock(&rwlock), "Failed to lock"); + zassert_ok(pthread_rwlock_rdlock(&rwlock), "Failed to lock"); } - printk("Main thread acquired RD lock\n"); + LOG_DBG("Main thread acquired RD lock"); usleep(USEC_PER_MSEC); - printk("Main thread releasing RD lock\n"); - zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); + LOG_DBG("Main thread releasing RD lock"); + zassert_ok(pthread_rwlock_unlock(&rwlock), "Failed to unlock"); - for (i = 0; i < N_THR; i++) { - zassert_false(pthread_join(newthread[i], &status), - "Failed to join"); + for (int i = 0; i < N_THR; i++) { + zassert_ok(pthread_join(newthread[i], &status), "Failed to join"); } - zassert_false(pthread_rwlock_destroy(&rwlock), - "Failed to destroy rwlock"); + zassert_ok(pthread_rwlock_destroy(&rwlock), "Failed to destroy rwlock"); } diff --git a/tests/posix/common/src/semaphore.c b/tests/posix/common/src/semaphore.c index fef4ddfb0fe97c5..fda34cfc23d5832 100644 --- a/tests/posix/common/src/semaphore.c +++ b/tests/posix/common/src/semaphore.c @@ -1,85 +1,52 @@ /* * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Meta * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include #include -#define STACK_SIZE (MAX(1024, PTHREAD_STACK_MIN) + CONFIG_TEST_EXTRA_STACK_SIZE) - -sem_t sema; -void *dummy_sem; - -struct sched_param schedparam; -int schedpolicy = SCHED_FIFO; - -static K_THREAD_STACK_DEFINE(stack, STACK_SIZE); - static void *child_func(void *p1) { - zassert_equal(sem_post(&sema), 0, "sem_post failed"); + sem_t *sem = (sem_t *)p1; + + zassert_equal(sem_post(sem), 0, "sem_post failed"); return NULL; } -void initialize_thread_attr(pthread_attr_t *attr) -{ - int ret; - - schedparam.sched_priority = 1; - - ret = pthread_attr_init(attr); - if (ret != 0) { - zassert_equal(pthread_attr_destroy(attr), 0, - "Unable to destroy pthread object attrib"); - zassert_equal(pthread_attr_init(attr), 0, - "Unable to create pthread object attrib"); - } - - pthread_attr_setstack(attr, &stack, STACK_SIZE); - pthread_attr_setschedpolicy(attr, schedpolicy); - pthread_attr_setschedparam(attr, &schedparam); -} - -ZTEST(posix_apis, test_semaphore) +static void semaphore_test(sem_t *sem) { pthread_t thread1, thread2; - pthread_attr_t attr1, attr2; int val, ret; struct timespec abstime; - initialize_thread_attr(&attr1); - /* TESTPOINT: Check if sema value is less than * CONFIG_SEM_VALUE_MAX */ - zassert_equal(sem_init(&sema, 0, (CONFIG_SEM_VALUE_MAX + 1)), -1, + zassert_equal(sem_init(sem, 0, (CONFIG_SEM_VALUE_MAX + 1)), -1, "value larger than %d\n", CONFIG_SEM_VALUE_MAX); zassert_equal(errno, EINVAL); - zassert_equal(sem_init(&sema, 0, 0), 0, "sem_init failed"); - - /* TESTPOINT: Call sem_post with invalid kobject */ - zassert_equal(sem_post(dummy_sem), -1, "sem_post of" - " invalid semaphore object didn't fail"); - zassert_equal(errno, EINVAL); + zassert_equal(sem_init(sem, 0, 0), 0, "sem_init failed"); /* TESTPOINT: Check if semaphore value is as set */ - zassert_equal(sem_getvalue(&sema, &val), 0); + zassert_equal(sem_getvalue(sem, &val), 0); zassert_equal(val, 0); /* TESTPOINT: Check if sema is acquired when it * is not available */ - zassert_equal(sem_trywait(&sema), -1); + zassert_equal(sem_trywait(sem), -1); zassert_equal(errno, EAGAIN); - ret = pthread_create(&thread1, &attr1, child_func, NULL); + ret = pthread_create(&thread1, NULL, child_func, sem); zassert_equal(ret, 0, "Thread creation failed"); zassert_equal(clock_gettime(CLOCK_REALTIME, &abstime), 0, @@ -90,41 +57,257 @@ ZTEST(posix_apis, test_semaphore) /* TESPOINT: Wait for 5 seconds and acquire sema given * by thread1 */ - zassert_equal(sem_timedwait(&sema, &abstime), 0); + zassert_equal(sem_timedwait(sem, &abstime), 0); /* TESTPOINT: Semaphore is already acquired, check if * no semaphore is available */ - zassert_equal(sem_timedwait(&sema, &abstime), -1); + zassert_equal(sem_timedwait(sem, &abstime), -1); zassert_equal(errno, ETIMEDOUT); - /* TESTPOINT: sem_destroy with invalid kobject */ - zassert_equal(sem_destroy(dummy_sem), -1, "invalid" - " semaphore is destroyed"); - zassert_equal(errno, EINVAL); - - zassert_equal(sem_destroy(&sema), 0, "semaphore is not destroyed"); - - zassert_equal(pthread_attr_destroy(&attr1), 0, - "Unable to destroy pthread object attrib"); + zassert_equal(sem_destroy(sem), 0, "semaphore is not destroyed"); /* TESTPOINT: Initialize sema with 1 */ - zassert_equal(sem_init(&sema, 0, 1), 0, "sem_init failed"); - zassert_equal(sem_getvalue(&sema, &val), 0); + zassert_equal(sem_init(sem, 0, 1), 0, "sem_init failed"); + zassert_equal(sem_getvalue(sem, &val), 0); zassert_equal(val, 1); - zassert_equal(sem_destroy(&sema), -1, "acquired semaphore" + zassert_equal(sem_destroy(sem), -1, "acquired semaphore" " is destroyed"); zassert_equal(errno, EBUSY); /* TESTPOINT: take semaphore which is initialized with 1 */ - zassert_equal(sem_trywait(&sema), 0); + zassert_equal(sem_trywait(sem), 0); - initialize_thread_attr(&attr2); - - zassert_equal(pthread_create(&thread2, &attr2, child_func, NULL), 0, + zassert_equal(pthread_create(&thread2, NULL, child_func, sem), 0, "Thread creation failed"); /* TESTPOINT: Wait and acquire semaphore till thread2 gives */ - zassert_equal(sem_wait(&sema), 0, "sem_wait failed"); + zassert_equal(sem_wait(sem), 0, "sem_wait failed"); + + /* Make sure the threads are terminated */ + zassert_ok(pthread_join(thread1, NULL)); + zassert_ok(pthread_join(thread2, NULL)); +} + +ZTEST(posix_apis, test_semaphore) +{ + sem_t sema; + + /* TESTPOINT: Call sem_post with invalid kobject */ + zassert_equal(sem_post(NULL), -1, "sem_post of" + " invalid semaphore object didn't fail"); + zassert_equal(errno, EINVAL); + + /* TESTPOINT: sem_destroy with invalid kobject */ + zassert_equal(sem_destroy(NULL), -1, "invalid" + " semaphore is destroyed"); + zassert_equal(errno, EINVAL); + + semaphore_test(&sema); +} + +int nsem_get_ref_count(sem_t *sem); +size_t nsem_get_list_len(void); +#define N_LOOPS 999 + +static void *nsem_open_func(void *p) +{ + const char *name = (char *)p; + + for (int i = 0; i < N_LOOPS; i++) { + zassert_not_null(sem_open(name, 0, 0, 0), "%s is NULL", name); + k_msleep(1); + } + + /* Unlink after finished opening */ + zassert_ok(sem_unlink(name)); + return NULL; +} + +static void *nsem_close_func(void *p) +{ + sem_t *sem = (sem_t *)p; + + /* Make sure that we have enough ref_count's initially */ + k_msleep(N_LOOPS >> 1); + + for (int i = 0; i < N_LOOPS; i++) { + zassert_ok(sem_close(sem)); + k_msleep(1); + } + + /* Close the last `sem` */ + zassert_ok(sem_close(sem)); + return NULL; +} + +ZTEST(posix_apis, test_named_semaphore) +{ + pthread_t thread1, thread2; + sem_t *sem1, *sem2, *different_sem1; + + /* If `name` is invalid */ + sem1 = sem_open(NULL, 0, 0, 0); + zassert_equal(errno, EINVAL); + zassert_equal_ptr(sem1, SEM_FAILED); + zassert_equal(nsem_get_list_len(), 0); + + /* Attempt to open a named sem that doesn't exist */ + sem1 = sem_open("sem1", 0, 0, 0); + zassert_equal(errno, ENOENT); + zassert_equal_ptr(sem1, SEM_FAILED); + zassert_equal(nsem_get_list_len(), 0); + + /* Name exceeds CONFIG_SEM_NAMELEN_MAX */ + char name_too_long[CONFIG_SEM_NAMELEN_MAX + 2]; + + for (size_t i = 0; i < sizeof(name_too_long) - 1; i++) { + name_too_long[i] = 'a'; + } + name_too_long[sizeof(name_too_long) - 1] = '\0'; + + sem1 = sem_open(name_too_long, 0, 0, 0); + zassert_equal(errno, ENAMETOOLONG, "\"%s\" should be longer than %d", name_too_long, + CONFIG_SEM_NAMELEN_MAX); + zassert_equal_ptr(sem1, SEM_FAILED); + zassert_equal(nsem_get_list_len(), 0); + + /* `value` greater than CONFIG_SEM_VALUE_MAX */ + sem1 = sem_open("sem1", O_CREAT, 0, (CONFIG_SEM_VALUE_MAX + 1)); + zassert_equal(errno, EINVAL); + zassert_equal_ptr(sem1, SEM_FAILED); + zassert_equal(nsem_get_list_len(), 0); + + /* Open named sem */ + sem1 = sem_open("sem1", O_CREAT, 0, 0); + zassert_equal(nsem_get_ref_count(sem1), 2); + zassert_equal(nsem_get_list_len(), 1); + sem2 = sem_open("sem2", O_CREAT, 0, 0); + zassert_equal(nsem_get_ref_count(sem2), 2); + zassert_equal(nsem_get_list_len(), 2); + + /* Open created named sem repeatedly */ + for (size_t i = 1; i <= N_LOOPS; i++) { + sem_t *new_sem1, *new_sem2; + + /* oflags are ignored (except when both O_CREAT & O_EXCL are set) */ + new_sem1 = sem_open("sem1", i % 2 == 0 ? O_CREAT : 0, 0, 0); + zassert_not_null(new_sem1); + zassert_equal_ptr(new_sem1, sem1); /* Should point to the same sem */ + new_sem2 = sem_open("sem2", i % 2 == 0 ? O_CREAT : 0, 0, 0); + zassert_not_null(new_sem2); + zassert_equal_ptr(new_sem2, sem2); + + /* ref_count should increment */ + zassert_equal(nsem_get_ref_count(sem1), 2 + i); + zassert_equal(nsem_get_ref_count(sem2), 2 + i); + + /* Should reuse the same named sem instead of creating another one */ + zassert_equal(nsem_get_list_len(), 2); + } + + /* O_CREAT and O_EXCL are set and the named semaphore already exists */ + zassert_equal_ptr((sem_open("sem1", O_CREAT | O_EXCL, 0, 0)), SEM_FAILED); + zassert_equal(errno, EEXIST); + zassert_equal(nsem_get_list_len(), 2); + + zassert_equal(sem_close(NULL), -1); + zassert_equal(errno, EINVAL); + zassert_equal(nsem_get_list_len(), 2); + + /* Close sem */ + for (size_t i = N_LOOPS; + /* close until one left, required by the test later */ + i >= 1; i--) { + zassert_ok(sem_close(sem1)); + zassert_equal(nsem_get_ref_count(sem1), 2 + i - 1); + + zassert_ok(sem_close(sem2)); + zassert_equal(nsem_get_ref_count(sem2), 2 + i - 1); + + zassert_equal(nsem_get_list_len(), 2); + } + + /* If `name` is invalid */ + zassert_equal(sem_unlink(NULL), -1); + zassert_equal(errno, EINVAL); + zassert_equal(nsem_get_list_len(), 2); + + /* Attempt to unlink a named sem that doesn't exist */ + zassert_equal(sem_unlink("sem3"), -1); + zassert_equal(errno, ENOENT); + zassert_equal(nsem_get_list_len(), 2); + + /* Name exceeds CONFIG_SEM_NAMELEN_MAX */ + char long_sem_name[CONFIG_SEM_NAMELEN_MAX + 2]; + + for (int i = 0; i < CONFIG_SEM_NAMELEN_MAX + 1; i++) { + long_sem_name[i] = 'a'; + } + long_sem_name[CONFIG_SEM_NAMELEN_MAX + 1] = '\0'; + + zassert_equal(sem_unlink(long_sem_name), -1); + zassert_equal(errno, ENAMETOOLONG); + zassert_equal(nsem_get_list_len(), 2); + + /* Unlink sem1 when it is still being used */ + zassert_equal(nsem_get_ref_count(sem1), 2); + zassert_ok(sem_unlink("sem1")); + /* sem won't be destroyed */ + zassert_equal(nsem_get_ref_count(sem1), 1); + zassert_equal(nsem_get_list_len(), 2); + + /* Create another sem with the name of an unlinked sem */ + different_sem1 = sem_open("sem1", O_CREAT, 0, 0); + zassert_not_null(different_sem1); + /* The created sem will be a different instance */ + zassert(different_sem1 != sem1, ""); + zassert_equal(nsem_get_list_len(), 3); + + /* Destruction of sem1 will be postponed until all references to the semaphore have been + * destroyed by calls to sem_close() + */ + zassert_ok(sem_close(sem1)); + zassert_equal(nsem_get_list_len(), 2); + + /* Closing a linked sem won't destroy the sem */ + zassert_ok(sem_close(sem2)); + zassert_equal(nsem_get_ref_count(sem2), 1); + zassert_equal(nsem_get_list_len(), 2); + + /* Instead the sem will be destroyed upon call to sem_unlink() */ + zassert_ok(sem_unlink("sem2")); + zassert_equal(nsem_get_list_len(), 1); + + /* What we have left open here is `different_sem` as "sem1", which has a ref_count of 2 */ + zassert_equal(nsem_get_ref_count(different_sem1), 2); + + /* Stress test: open & close "sem1" repeatedly */ + zassert_ok(pthread_create(&thread1, NULL, nsem_open_func, "sem1")); + zassert_ok(pthread_create(&thread2, NULL, nsem_close_func, different_sem1)); + + /* Make sure the threads are terminated */ + zassert_ok(pthread_join(thread1, NULL)); + zassert_ok(pthread_join(thread2, NULL)); + + /* All named semaphores should be destroyed here */ + zassert_equal(nsem_get_list_len(), 0); + + /* Create a new named sem to be used in the normal semaphore test */ + sem1 = sem_open("nsem", O_CREAT, 0, 0); + zassert_equal(nsem_get_list_len(), 1); + zassert_equal(nsem_get_ref_count(sem1), 2); + + /* Run the semaphore test with the created named semaphore */ + semaphore_test(sem1); + + /* List length and ref_count shouldn't change after the test */ + zassert_equal(nsem_get_list_len(), 1); + zassert_equal(nsem_get_ref_count(sem1), 2); + + /* Unless it is unlinked and closed */ + sem_unlink("nsem"); + sem_close(sem1); + zassert_equal(nsem_get_list_len(), 0); } diff --git a/tests/posix/headers/src/semaphore_h.c b/tests/posix/headers/src/semaphore_h.c index 0ac1de36f2ebe6e..b4c2e151fa1d66b 100644 --- a/tests/posix/headers/src/semaphore_h.c +++ b/tests/posix/headers/src/semaphore_h.c @@ -22,15 +22,15 @@ ZTEST(posix_headers, test_semaphore_h) /* zassert_not_equal(SEM_FAILED, (sem_t *)42); */ /* not implemented */ if (IS_ENABLED(CONFIG_POSIX_API)) { - /* zassert_not_null(sem_close); */ /* not implemented */ + zassert_not_null(sem_close); zassert_not_null(sem_destroy); zassert_not_null(sem_getvalue); zassert_not_null(sem_init); - /* zassert_not_null(sem_open); */ /* not implemented */ + zassert_not_null(sem_open); zassert_not_null(sem_post); zassert_not_null(sem_timedwait); zassert_not_null(sem_trywait); - /* zassert_not_null(sem_unlink); */ /* not implemented */ + zassert_not_null(sem_unlink); zassert_not_null(sem_wait); } } diff --git a/tests/subsys/fs/ext2/testcase.yaml b/tests/subsys/fs/ext2/testcase.yaml index 7466e0984b9789c..bb4402c9b0ec582 100644 --- a/tests/subsys/fs/ext2/testcase.yaml +++ b/tests/subsys/fs/ext2/testcase.yaml @@ -19,6 +19,8 @@ tests: - EXTRA_DTC_OVERLAY_FILE="ramdisk_big.overlay" filesystem.ext2.sdcard: + simulation_exclude: + - renode platform_allow: - hifive_unmatched - bl5340_dvk_cpuapp diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c b/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c index 50ac67d43b23fc3..99dee33e380e354 100644 --- a/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c @@ -248,7 +248,7 @@ static void cleanup_test(void *p) void test_main(void) { while (test_state.test_set < CB_NOTIFICATION_TEST_SET_COUNT) { - ztest_run_all(&test_state); + ztest_run_all(&test_state, false, 1, 1); ++test_state.test_set; } diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/main.c b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/main.c index c387c3b4812a842..c3a3c71d2b2bfaf 100644 --- a/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/main.c +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_datetime/src/main.c @@ -1458,7 +1458,7 @@ static void cleanup_test(void *p) void test_main(void) { while (test_state.test_set < OS_MGMT_DATETIME_TEST_SET_COUNT) { - ztest_run_all(&test_state); + ztest_run_all(&test_state, false, 1, 1); ++test_state.test_set; } diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c index 8ffc2a354b80704..d07b8ed6d4def8e 100644 --- a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c @@ -1499,7 +1499,7 @@ static void cleanup_test(void *p) void test_main(void) { while (test_state.test_set < OS_MGMT_TEST_SET_COUNT) { - ztest_run_all(&test_state); + ztest_run_all(&test_state, false, 1, 1); ++test_state.test_set; } diff --git a/tests/subsys/pm/device_driver_init/src/main.c b/tests/subsys/pm/device_driver_init/src/main.c index f423b1d683c081f..d2f9f78fd3aaa29 100644 --- a/tests/subsys/pm/device_driver_init/src/main.c +++ b/tests/subsys/pm/device_driver_init/src/main.c @@ -32,23 +32,26 @@ ZTEST(device_driver_init, test_device_driver_init) #if IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) enum pm_device_state state; int rc; - + state = -1; + zassert_equal(strcmp("", pm_device_state_str(state)), 0, "Invalid device state"); /* No device runtime PM, starts on */ DEVICE_STATE_IS(DT_NODELABEL(test_reg), PM_DEVICE_STATE_ACTIVE); DEVICE_STATE_IS(DT_NODELABEL(test_reg_chained), PM_DEVICE_STATE_ACTIVE); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg), GPIO_OUTPUT_HIGH); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_chained), GPIO_OUTPUT_HIGH); - + zassert_equal(strcmp("active", pm_device_state_str(state)), 0, "Invalid device state"); /* Device powered, zephyr,pm-device-runtime-auto, starts suspended */ DEVICE_STATE_IS(DT_NODELABEL(test_reg_chained_auto), PM_DEVICE_STATE_SUSPENDED); DEVICE_STATE_IS(DT_NODELABEL(test_reg_auto), PM_DEVICE_STATE_SUSPENDED); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_chained_auto), GPIO_OUTPUT_LOW); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto), GPIO_OUTPUT_LOW); + zassert_equal(strcmp("suspended", pm_device_state_str(state)), 0, "Invalid device state"); /* Device not powered, starts off */ DEVICE_STATE_IS(DT_NODELABEL(test_reg_auto_chained), PM_DEVICE_STATE_OFF); DEVICE_STATE_IS(DT_NODELABEL(test_reg_auto_chained_auto), PM_DEVICE_STATE_OFF); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto_chained), GPIO_DISCONNECTED); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto_chained_auto), GPIO_DISCONNECTED); + zassert_equal(strcmp("off", pm_device_state_str(state)), 0, "Invalid device state"); #else /* Every regulator should be in "active" mode automatically. * State checking via GPIO as PM API is disabled. diff --git a/tests/unit/util/main.c b/tests/unit/util/main.c index e10455e263a6629..fc8af19d34a893b 100644 --- a/tests/unit/util/main.c +++ b/tests/unit/util/main.c @@ -646,4 +646,75 @@ ZTEST(util, test_IF_DISABLED) #undef test_IF_DISABLED_FLAG_B } +ZTEST(util, test_mem_xor_n) +{ + const size_t max_len = 128; + uint8_t expected_result[max_len]; + uint8_t src1[max_len]; + uint8_t src2[max_len]; + uint8_t dst[max_len]; + + memset(expected_result, 0, sizeof(expected_result)); + memset(src1, 0, sizeof(src1)); + memset(src2, 0, sizeof(src2)); + memset(dst, 0, sizeof(dst)); + + for (size_t i = 0U; i < max_len; i++) { + const size_t len = i; + + for (size_t j = 0U; j < len; j++) { + src1[j] = 0x33; + src2[j] = 0x0F; + expected_result[j] = 0x3C; + } + + mem_xor_n(dst, src1, src2, len); + zassert_mem_equal(expected_result, dst, len); + } +} + +ZTEST(util, test_mem_xor_32) +{ + uint8_t expected_result[4]; + uint8_t src1[4]; + uint8_t src2[4]; + uint8_t dst[4]; + + memset(expected_result, 0, sizeof(expected_result)); + memset(src1, 0, sizeof(src1)); + memset(src2, 0, sizeof(src2)); + memset(dst, 0, sizeof(dst)); + + for (size_t i = 0U; i < 4; i++) { + src1[i] = 0x43; + src2[i] = 0x0F; + expected_result[i] = 0x4C; + } + + mem_xor_32(dst, src1, src2); + zassert_mem_equal(expected_result, dst, 4); +} + +ZTEST(util, test_mem_xor_128) +{ + uint8_t expected_result[16]; + uint8_t src1[16]; + uint8_t src2[16]; + uint8_t dst[16]; + + memset(expected_result, 0, sizeof(expected_result)); + memset(src1, 0, sizeof(src1)); + memset(src2, 0, sizeof(src2)); + memset(dst, 0, sizeof(dst)); + + for (size_t i = 0U; i < 16; i++) { + src1[i] = 0x53; + src2[i] = 0x0F; + expected_result[i] = 0x5C; + } + + mem_xor_128(dst, src1, src2); + zassert_mem_equal(expected_result, dst, 16); +} + ZTEST_SUITE(util, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/ztest/base/src/main_deprecated.c b/tests/ztest/base/src/main_deprecated.c deleted file mode 100644 index 0a561cc8066eab1..000000000000000 --- a/tests/ztest/base/src/main_deprecated.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -static void test_empty_test(void) -{ -} - -static void test_assert_tests(void) -{ - zassert_true(1); - zassert_false(0); - zassert_is_null(NULL, NULL); - zassert_not_null("foo", NULL); - zassert_equal(1, 1); - zassert_equal_ptr(NULL, NULL, NULL); -} - -static void test_assert_mem_equal(void) -{ - static const uint32_t expected[4] = { - 0x1234, - 0x5678, - 0x9ABC, - 0xDEF0 - }; - uint32_t actual[4] = {0}; - - memcpy(actual, expected, sizeof(actual)); - zassert_mem_equal(actual, expected, sizeof(expected), NULL); -} - -void test_main(void) -{ - ztest_test_suite(framework_tests, - ztest_unit_test(test_empty_test), - ztest_unit_test(test_assert_tests), - ztest_unit_test(test_assert_mem_equal) - ); - - ztest_run_test_suite(framework_tests); -} diff --git a/tests/ztest/error_hook/src/main.c b/tests/ztest/error_hook/src/main.c index e38b3111cf3c568..dfa998e0075d881 100644 --- a/tests/ztest/error_hook/src/main.c +++ b/tests/ztest/error_hook/src/main.c @@ -424,7 +424,7 @@ ZTEST(fail_assume_in_test, test_to_skip) void test_main(void) { - ztest_run_test_suites(NULL); + ztest_run_test_suites(NULL, false, 1, 1); /* Can't run ztest_verify_all_test_suites_ran() since some tests are * skipped by design. */ diff --git a/west.yml b/west.yml index 71d85b477639d03..83b7e41b0904ea6 100644 --- a/west.yml +++ b/west.yml @@ -152,7 +152,7 @@ manifest: groups: - hal - name: hal_espressif - revision: e98ce93e916eebdc4a0c5bceef864289447e3d63 + revision: a248460c09b6588428f6edaf5ebe312648c7360c path: modules/hal/espressif west-commands: west/west-commands.yml groups: @@ -183,7 +183,7 @@ manifest: groups: - hal - name: hal_nordic - revision: b9633ecea67bf52925d4c61455046223b46402b1 + revision: b55cfbbf0221d709560c2e438beef66842ada272 path: modules/hal/nordic groups: - hal @@ -193,7 +193,7 @@ manifest: groups: - hal - name: hal_nxp - revision: ed3efff426ce56230be189d99ce985ceafece4a4 + revision: 12970d629fc900010dab5cf250be70287bf9e443 path: modules/hal/nxp groups: - hal @@ -219,7 +219,7 @@ manifest: groups: - hal - name: hal_silabs - revision: 7a6ba7ce989c3c466b4cb450e44858a3bb0a949a + revision: e670e749760e7a77a75c69f2c932b345cc0e212f path: modules/hal/silabs groups: - hal @@ -282,7 +282,7 @@ manifest: groups: - crypto - name: mcuboot - revision: e9131ee8b8ab9306d8f6ad410fd1e3d8a820ce10 + revision: b994ba2ce29425587957dcbb6c96d4e1872b5737 path: bootloader/mcuboot - name: mipi-sys-t path: modules/debug/mipi-sys-t @@ -295,7 +295,7 @@ manifest: groups: - tools - name: nrf_hw_models - revision: 9b985ea6bc237b6ae06f48eb228f2ac7f6e3b96b + revision: c744f2c762aad79e59bd7e99002f2fcab0a2f288 path: modules/bsim_hw_models/nrf_hw_models - name: open-amp revision: da78aea63159771956fe0c9263f2e6985b66e9d5