From 6305c17d6e4b92b574f4a3b37e717a2e8b373be6 Mon Sep 17 00:00:00 2001 From: Maureen Helm Date: Sat, 1 Jun 2024 13:51:24 -0500 Subject: [PATCH 001/981] manifest: Update hal_adi to pick up newlib compatibility fix Updates the hal_adi module to pick up a fix for building with newlib. Signed-off-by: Maureen Helm --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 1d8c79fc3d1663..dc048e90c76282 100644 --- a/west.yml +++ b/west.yml @@ -137,7 +137,7 @@ manifest: groups: - fs - name: hal_adi - revision: 674d10b0a1aad4cf4b7b90ca52dfd4a494ab9e52 + revision: 2858da5ab4a7a01cde48a41818a1a6693529f68d path: modules/hal/adi groups: - hal From 8edbbdf332cd35b9713547e37788a9f5908fbf56 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 3 Jun 2024 13:08:22 +0200 Subject: [PATCH 002/981] dts: bindings: can: loopback: the CAN loopback driver supports CAN FD The CAN loopback driver supports CAN FD. Change the binding to reflect this. No functional changes. Signed-off-by: Henrik Brix Andersen --- dts/bindings/can/zephyr,can-loopback.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/bindings/can/zephyr,can-loopback.yaml b/dts/bindings/can/zephyr,can-loopback.yaml index 531c6d965bf8c0..af93433bf041b6 100644 --- a/dts/bindings/can/zephyr,can-loopback.yaml +++ b/dts/bindings/can/zephyr,can-loopback.yaml @@ -5,4 +5,4 @@ description: Zephyr emulated CAN loopback controller compatible: "zephyr,can-loopback" -include: can-controller.yaml +include: can-fd-controller.yaml From 64e9ba3742b749731db18b3fa4013b98b6757096 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 3 Jun 2024 13:09:27 +0200 Subject: [PATCH 003/981] dts: bindings: can: native linux: the CAN Linux driver supports CAN FD The native Linux CAN driver supports CAN FD. Change the binding to reflect this. No functional changes. Signed-off-by: Henrik Brix Andersen --- dts/bindings/can/zephyr,native-linux-can.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/bindings/can/zephyr,native-linux-can.yaml b/dts/bindings/can/zephyr,native-linux-can.yaml index 4175617403b34f..b854984ece08a2 100644 --- a/dts/bindings/can/zephyr,native-linux-can.yaml +++ b/dts/bindings/can/zephyr,native-linux-can.yaml @@ -5,7 +5,7 @@ description: Zephyr CAN driver using Linux SocketCAN compatible: "zephyr,native-linux-can" -include: can-controller.yaml +include: can-fd-controller.yaml properties: host-interface: From 5bd1689ac8eb52f2951eb1d4ad4820ed95aa8d1f Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 3 Jun 2024 11:11:58 +0200 Subject: [PATCH 004/981] boards: st: stm32c0116_dk defines the select pin with zephyr,code Define the select_key with the correct zephyr,code which is Signed-off-by: Francois Ramu --- boards/st/stm32c0116_dk/stm32c0116_dk.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/st/stm32c0116_dk/stm32c0116_dk.dts b/boards/st/stm32c0116_dk/stm32c0116_dk.dts index f9791268886a9b..79b4db1fa25834 100644 --- a/boards/st/stm32c0116_dk/stm32c0116_dk.dts +++ b/boards/st/stm32c0116_dk/stm32c0116_dk.dts @@ -53,7 +53,7 @@ select_key { press-thresholds-mv = <0>; - zephyr,code = ; + zephyr,code = ; }; left_key { From 68adc77cbdb168838e76a63412dd1fb71d7d1c57 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 3 Jun 2024 11:08:23 +0200 Subject: [PATCH 005/981] boards nrf_bsim: Add NVIC_GetEnableIRQ() Provide a replacement for CMSIS' NVIC_GetEnableIRQ() as some applications use it. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/common/cmsis/cmsis.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/boards/native/nrf_bsim/common/cmsis/cmsis.c b/boards/native/nrf_bsim/common/cmsis/cmsis.c index 1694bc1da3406a..e80aea6b4ff607 100644 --- a/boards/native/nrf_bsim/common/cmsis/cmsis.c +++ b/boards/native/nrf_bsim/common/cmsis/cmsis.c @@ -35,6 +35,11 @@ void NVIC_EnableIRQ(IRQn_Type IRQn) hw_irq_ctrl_enable_irq(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); } +uint32_t NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + return hw_irq_ctrl_is_irq_enabled(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); +} + void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { hw_irq_ctrl_prio_set(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn, priority); From 92002b2dff24a923cae5c6ab5b00a4dcbb25c624 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Thu, 30 May 2024 14:48:25 +0200 Subject: [PATCH 006/981] Bluetooth: CAP: Implement bt_cap_initiator_unregister_cb Implement function to unregisterd the CAP initiator callbacks. Signed-off-by: Emil Gydesen --- include/zephyr/bluetooth/audio/cap.h | 10 ++++++++++ subsys/bluetooth/audio/cap_initiator.c | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index 6bf5e1b018e12b..c5c4bbea6e8aed 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -296,6 +296,16 @@ struct bt_cap_unicast_audio_stop_param { */ int bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb *cb); +/** + * @brief Unregister Common Audio Profile Initiator callbacks + * + * @param cb The callback structure that was previously registered. + * + * @retval 0 Success + * @retval -EINVAL @p cb is NULL or @p cb was not registered + */ +int bt_cap_initiator_unregister_cb(const struct bt_cap_initiator_cb *cb); + /** * @brief Setup and start unicast audio streams for a set of devices. * diff --git a/subsys/bluetooth/audio/cap_initiator.c b/subsys/bluetooth/audio/cap_initiator.c index 3fd5199d5c73d0..61257e8a013e55 100644 --- a/subsys/bluetooth/audio/cap_initiator.c +++ b/subsys/bluetooth/audio/cap_initiator.c @@ -53,6 +53,23 @@ int bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb *cb) return 0; } +int bt_cap_initiator_unregister_cb(const struct bt_cap_initiator_cb *cb) +{ + CHECKIF(cb == NULL) { + LOG_DBG("cb is NULL"); + return -EINVAL; + } + + CHECKIF(cap_cb != cb) { + LOG_DBG("cb is not registered"); + return -EINVAL; + } + + cap_cb = NULL; + + return 0; +} + struct valid_metadata_param { bool stream_context_found; bool valid; From 435b72dc18c8f959163e38d87ba133d7a4c17d1b Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Wed, 29 May 2024 17:40:27 +0200 Subject: [PATCH 007/981] llext: add a test for the pre_located feature This test checks that the pre_located feature works as expected. It creates a new extension that is manually relocated to a specific address via the add_llext_command() CMake function invoking a custom linker command. The test then loads the extension setting the pre_located option and checks that the symbol is resolved properly. Signed-off-by: Luca Burelli --- tests/subsys/llext/simple/CMakeLists.txt | 25 ++++++++++------- .../subsys/llext/simple/src/pre_located_ext.c | 19 +++++++++++++ .../llext/simple/src/test_llext_simple.c | 27 +++++++++++++++++++ 3 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 tests/subsys/llext/simple/src/pre_located_ext.c diff --git a/tests/subsys/llext/simple/CMakeLists.txt b/tests/subsys/llext/simple/CMakeLists.txt index 2a677470f66669..2337b3a80c93cd 100644 --- a/tests/subsys/llext/simple/CMakeLists.txt +++ b/tests/subsys/llext/simple/CMakeLists.txt @@ -23,6 +23,10 @@ if(CONFIG_ARM) endif() endif() +if (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE AND CONFIG_XTENSA) + list(APPEND ext_names pre_located) +endif() + # generate extension targets foreach extension given by 'ext_names' foreach(ext_name ${ext_names}) set(ext_src ${PROJECT_SOURCE_DIR}/src/${ext_name}_ext.c) @@ -45,12 +49,15 @@ if(NOT CONFIG_LLEXT_TYPE_ELF_OBJECT) ) endif() -# Add a dummy custom processing command to test add_llext_command -get_target_property(proc_in_file hello_world_ext lib_output) -get_target_property(proc_out_file hello_world_ext pkg_input) -add_llext_command( - TARGET hello_world_ext - POST_BUILD - COMMAND echo "dummy patching ${proc_in_file} to create ${proc_out_file}" - COMMAND ${CMAKE_COMMAND} -E copy ${proc_in_file} ${proc_out_file} -) +if (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE AND CONFIG_XTENSA) + # Manually fix the pre_located extension's text address at a multiple of 4 + get_target_property(pre_located_target pre_located_ext lib_target) + get_target_property(pre_located_file pre_located_ext pkg_input) + add_llext_command( + TARGET pre_located_ext + POST_BUILD + COMMAND ${CMAKE_C_COMPILER} + -Wl,-r -Wl,-Ttext=0xbada110c -nostdlib -nodefaultlibs -nostartfiles + $ -o ${pre_located_file} + ) +endif() diff --git a/tests/subsys/llext/simple/src/pre_located_ext.c b/tests/subsys/llext/simple/src/pre_located_ext.c new file mode 100644 index 00000000000000..1308c8d662fc67 --- /dev/null +++ b/tests/subsys/llext/simple/src/pre_located_ext.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Arduino SA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file contains a simple test extension that defines an entry point + * in the .text section. The entry point is never called, but the symbol + * address is fixed via a linker call and then checked by the test. + */ + +#include + +void test_entry(void) +{ + /* This function is never called */ +} +LL_EXTENSION_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/test_llext_simple.c b/tests/subsys/llext/simple/src/test_llext_simple.c index 2552844946e44c..68b318f5e1c80c 100644 --- a/tests/subsys/llext/simple/src/test_llext_simple.c +++ b/tests/subsys/llext/simple/src/test_llext_simple.c @@ -237,6 +237,33 @@ static LLEXT_CONST uint8_t multi_file_ext[] __aligned(4) = { LLEXT_LOAD_UNLOAD(multi_file, true, NULL) #endif +#if defined(CONFIG_LLEXT_TYPE_ELF_RELOCATABLE) && defined(CONFIG_XTENSA) +static LLEXT_CONST uint8_t pre_located_ext[] __aligned(4) = { + #include "pre_located.inc" +}; + +ZTEST(llext, test_pre_located) +{ + struct llext_buf_loader buf_loader = + LLEXT_BUF_LOADER(pre_located_ext, ARRAY_SIZE(pre_located_ext)); + struct llext_loader *loader = &buf_loader.loader; + struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; + struct llext *ext = NULL; + const void *test_entry_fn; + int res; + + /* load the extension trying to respect the addresses in the ELF */ + ldr_parm.pre_located = true; + res = llext_load(loader, "pre_located", &ext, &ldr_parm); + zassert_ok(res, "load should succeed"); + + /* check the function address is the expected one */ + test_entry_fn = llext_find_sym(&ext->exp_tab, "test_entry"); + zassert_equal(test_entry_fn, (void *)0xbada110c, "test_entry should be at 0xbada110c"); + + llext_unload(&ext); +} +#endif /* * Ensure that EXPORT_SYMBOL does indeed provide a symbol and a valid address From 05ad2565fadbece12c9a59967fa7dc945acd5ae2 Mon Sep 17 00:00:00 2001 From: Joel Guittet Date: Mon, 27 May 2024 15:14:46 +0200 Subject: [PATCH 008/981] llext: add _POSIX_C_SOURCE definition to build shell Fix implicit-function-declaration warning while building the llext shell. Signed-off-by: Joel Guittet --- subsys/llext/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/llext/CMakeLists.txt b/subsys/llext/CMakeLists.txt index b129dc7f94314f..d08e1c8aee0e3d 100644 --- a/subsys/llext/CMakeLists.txt +++ b/subsys/llext/CMakeLists.txt @@ -1,5 +1,7 @@ if(CONFIG_LLEXT) zephyr_library() + # For strnlen() + zephyr_library_compile_definitions(-D_POSIX_C_SOURCE=200809L) zephyr_library_sources(llext.c llext_export.c buf_loader.c) zephyr_library_sources_ifdef(CONFIG_LLEXT_SHELL shell.c) endif() From 8aa6ae43ce47a990d81ea06d84fa26a584d16a30 Mon Sep 17 00:00:00 2001 From: Mathieu Choplain Date: Mon, 6 May 2024 13:03:26 +0200 Subject: [PATCH 009/981] llext: add support for SLID-based linking This commit introduces support for an alternate linking method in the LLEXT subsystem, called "SLID" (short for Symbol Link Identifier), enabled by the CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID Kconfig option. SLID-based linking uses a unique identifier (integer) to identify exported symbols, instead of using the symbol name as done currently. This approach provides several benefits: * linking is faster because the comparison operation to determine whether we found the correct symbol in the export table is now an integer compare, instead of a string compare * binary size is reduced as symbol names can be dropped from the binary * confidentiality is improved as a side-effect, as symbol names are no longer present in the binary Signed-off-by: Mathieu Choplain --- CMakeLists.txt | 15 + boards/qemu/x86/qemu_x86_tiny.ld | 4 + cmake/llext-edk.cmake | 5 + cmake/modules/extensions.cmake | 20 + include/zephyr/arch/arc/v2/linker.ld | 4 + .../arch/arm/cortex_a_r/scripts/linker.ld | 4 + .../arch/arm/cortex_m/scripts/linker.ld | 4 + include/zephyr/arch/arm64/scripts/linker.ld | 4 + include/zephyr/arch/mips/linker.ld | 4 + include/zephyr/arch/nios2/linker.ld | 4 + include/zephyr/arch/posix/linker.ld | 4 + include/zephyr/arch/riscv/common/linker.ld | 4 + include/zephyr/arch/sparc/linker.ld | 4 + include/zephyr/arch/x86/ia32/linker.ld | 4 + include/zephyr/arch/x86/intel64/linker.ld | 3 + include/zephyr/linker/llext-sections.ld | 19 + include/zephyr/llext/symbol.h | 27 +- scripts/build/llext_inject_slids.py | 196 +++++++++ scripts/build/llext_prepare_exptab.py | 377 ++++++++++++++++++ scripts/build/llext_slidlib.py | 65 +++ soc/andestech/ae350/linker.ld | 4 + soc/cdns/dc233c/include/xtensa-dc233c.ld | 4 + .../include/xtensa-sample-controller.ld | 4 + soc/espressif/esp32/default.ld | 4 + soc/espressif/esp32/default_appcpu.ld | 4 + soc/espressif/esp32c3/default.ld | 4 + soc/espressif/esp32s2/default.ld | 4 + soc/espressif/esp32s3/default.ld | 4 + soc/espressif/esp32s3/default_appcpu.ld | 4 + soc/infineon/cat1b/cyw20829/linker.ld | 4 + soc/intel/intel_adsp/ace/ace-link.ld | 4 + .../cavs/include/xtensa-cavs-linker.ld | 4 + soc/ite/ec/it8xxx2/linker.ld | 4 + soc/nxp/imx/imx8/adsp/linker.ld | 4 + soc/nxp/imx/imx8m/adsp/linker.ld | 4 + soc/nxp/imx/imx8ulp/adsp/linker.ld | 4 + soc/nxp/imx/imx8x/adsp/linker.ld | 4 + soc/nxp/imx/imx9/a55/linker.ld | 4 + soc/nxp/imxrt/imxrt5xx/f1/linker.ld | 4 + soc/openisa/rv32m1/linker.ld | 4 + soc/st/stm32/stm32mp1x/linker.ld | 5 + subsys/llext/Kconfig | 15 + subsys/llext/llext.c | 28 +- .../llext/simple/src/test_llext_simple.c | 21 +- tests/subsys/llext/simple/testcase.yaml | 68 ++++ 45 files changed, 981 insertions(+), 7 deletions(-) create mode 100644 include/zephyr/linker/llext-sections.ld create mode 100755 scripts/build/llext_inject_slids.py create mode 100755 scripts/build/llext_prepare_exptab.py create mode 100755 scripts/build/llext_slidlib.py diff --git a/CMakeLists.txt b/CMakeLists.txt index c6b173501495f9..05c50b119bc415 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1888,6 +1888,21 @@ if(CONFIG_BUILD_OUTPUT_INFO_HEADER) ) endif() +if (CONFIG_LLEXT AND CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) + #slidgen must be the first post-build command to be executed + #on the Zephyr ELF to ensure that all other commands, such as + #binary file generation, are operating on a preparated ELF. + list(PREPEND + post_build_commands + COMMAND ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/llext_prepare_exptab.py + --elf-file ${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME} + --slid-listing ${PROJECT_BINARY_DIR}/slid_listing.txt + -vvv + ) + +endif() + if(NOT CMAKE_C_COMPILER_ID STREQUAL "ARMClang") set(check_init_priorities_input $,${BYPRODUCT_KERNEL_EXE_NAME},${BYPRODUCT_KERNEL_ELF_NAME}> diff --git a/boards/qemu/x86/qemu_x86_tiny.ld b/boards/qemu/x86/qemu_x86_tiny.ld index 3b3ecde113cc34..1b635f331ee371 100644 --- a/boards/qemu/x86/qemu_x86_tiny.ld +++ b/boards/qemu/x86/qemu_x86_tiny.ld @@ -254,6 +254,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /DISCARD/ : { *(.plt) diff --git a/cmake/llext-edk.cmake b/cmake/llext-edk.cmake index 9501133f3ab382..da9c33b127f3be 100644 --- a/cmake/llext-edk.cmake +++ b/cmake/llext-edk.cmake @@ -31,6 +31,11 @@ cmake_minimum_required(VERSION 3.20.0) +if (CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) + message(FATAL_ERROR + "The LLEXT EDK is not compatible with CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID.") +endif() + set(llext_edk ${PROJECT_BINARY_DIR}/${llext_edk_name}) set(llext_edk_inc ${llext_edk}/include) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 2c1e1c6635542b..9fe387e2388159 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -5431,6 +5431,23 @@ function(add_llext_target target_name) COMMAND_EXPAND_LISTS ) + # LLEXT ELF processing for importing via SLID + # + # This command must be executed as last step of the packaging process, + # to ensure that the ELF processed for binary generation contains SLIDs. + # If executed too early, it is possible that some tools executed to modify + # the ELF file (e.g., strip) undo the work performed here. + if (CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) + set(slid_inject_cmd + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/llext_inject_slids.py + --elf-file ${llext_pkg_output} + -vvv + ) + else() + set(slid_inject_cmd ${CMAKE_COMMAND} -E true) + endif() + # Type-specific packaging of the built binary file into an .llext file if(CONFIG_LLEXT_TYPE_ELF_OBJECT) @@ -5438,6 +5455,7 @@ function(add_llext_target target_name) add_custom_command( OUTPUT ${llext_pkg_output} COMMAND ${CMAKE_COMMAND} -E copy ${llext_pkg_input} ${llext_pkg_output} + COMMAND ${slid_inject_cmd} DEPENDS ${llext_proc_target} ${llext_pkg_input} ) @@ -5453,6 +5471,7 @@ function(add_llext_target target_name) $${llext_pkg_input} $${llext_pkg_output} $ + COMMAND ${slid_inject_cmd} DEPENDS ${llext_proc_target} ${llext_pkg_input} ) @@ -5467,6 +5486,7 @@ function(add_llext_target target_name) $${llext_pkg_input} $${llext_pkg_output} $ + COMMAND ${slid_inject_cmd} DEPENDS ${llext_proc_target} ${llext_pkg_input} ) diff --git a/include/zephyr/arch/arc/v2/linker.ld b/include/zephyr/arch/arc/v2/linker.ld index a7751d961194e6..c65aa5a648412e 100644 --- a/include/zephyr/arch/arc/v2/linker.ld +++ b/include/zephyr/arch/arc/v2/linker.ld @@ -81,6 +81,10 @@ SECTIONS { #include +#ifdef CONFIG_LLEXT +#include +#endif + GROUP_START(ROMABLE_REGION) SECTION_PROLOGUE(_TEXT_SECTION_NAME,,ALIGN(1024)) { diff --git a/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld b/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld index 947c18de313494..cffe2f3856e001 100644 --- a/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld @@ -98,6 +98,10 @@ SECTIONS { #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld index 88598cf5790ebd..094e4a5303f970 100644 --- a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -113,6 +113,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/include/zephyr/arch/arm64/scripts/linker.ld b/include/zephyr/arch/arm64/scripts/linker.ld index 5a8e1404a98ae7..d2f573520c12a7 100644 --- a/include/zephyr/arch/arm64/scripts/linker.ld +++ b/include/zephyr/arch/arm64/scripts/linker.ld @@ -77,6 +77,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/include/zephyr/arch/mips/linker.ld b/include/zephyr/arch/mips/linker.ld index cbff890822c723..f7479c23e36b56 100644 --- a/include/zephyr/arch/mips/linker.ld +++ b/include/zephyr/arch/mips/linker.ld @@ -46,6 +46,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + SECTION_PROLOGUE(_VECTOR_SECTION_NAME,,) { . = ALIGN(0x1000); diff --git a/include/zephyr/arch/nios2/linker.ld b/include/zephyr/arch/nios2/linker.ld index f7ba64088fc6ed..d65805ba7cf1e9 100644 --- a/include/zephyr/arch/nios2/linker.ld +++ b/include/zephyr/arch/nios2/linker.ld @@ -85,6 +85,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to * 'nios2-zephyr-elf-ld --verbose', before text section. diff --git a/include/zephyr/arch/posix/linker.ld b/include/zephyr/arch/posix/linker.ld index 06dfb3254f1724..0943546c0c7b0d 100644 --- a/include/zephyr/arch/posix/linker.ld +++ b/include/zephyr/arch/posix/linker.ld @@ -21,6 +21,10 @@ SECTIONS { +#ifdef CONFIG_LLEXT +#include +#endif + SECTION_PROLOGUE(rom_start,,) { /* Located in generated directory. This file is populated by the diff --git a/include/zephyr/arch/riscv/common/linker.ld b/include/zephyr/arch/riscv/common/linker.ld index ccb16cc2c670b4..8ef264b9f1a644 100644 --- a/include/zephyr/arch/riscv/common/linker.ld +++ b/include/zephyr/arch/riscv/common/linker.ld @@ -122,6 +122,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * The .plt and .iplt are here according to * 'riscv32-zephyr-elf-ld --verbose', before text section. diff --git a/include/zephyr/arch/sparc/linker.ld b/include/zephyr/arch/sparc/linker.ld index 725339ef0b7cd8..ccf333d4863c40 100644 --- a/include/zephyr/arch/sparc/linker.ld +++ b/include/zephyr/arch/sparc/linker.ld @@ -23,6 +23,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + __rom_region_start = .; SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) diff --git a/include/zephyr/arch/x86/ia32/linker.ld b/include/zephyr/arch/x86/ia32/linker.ld index 69ff541232695d..e796b3c3e85f71 100644 --- a/include/zephyr/arch/x86/ia32/linker.ld +++ b/include/zephyr/arch/x86/ia32/linker.ld @@ -77,6 +77,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /DISCARD/ : { *(.plt) diff --git a/include/zephyr/arch/x86/intel64/linker.ld b/include/zephyr/arch/x86/intel64/linker.ld index 8949b94e657fdf..1bc014570c6389 100644 --- a/include/zephyr/arch/x86/intel64/linker.ld +++ b/include/zephyr/arch/x86/intel64/linker.ld @@ -236,4 +236,7 @@ SECTIONS .shstrtab 0 : { *(.shstrtab) } #endif +#ifdef CONFIG_LLEXT + #include +#endif } diff --git a/include/zephyr/linker/llext-sections.ld b/include/zephyr/linker/llext-sections.ld new file mode 100644 index 00000000000000..b8cc32e3d1bf1a --- /dev/null +++ b/include/zephyr/linker/llext-sections.ld @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + + /* + * Special section used by LLEXT if CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID + * is enabled. Declare this section to prevent it from being considered orphan. + * + * This section is used to temporarily save the exported symbols' names in the + * Zephyr ELF for post-processing, but it is not included in the final binary. + * + * NOTE: This section MUST start at address 0, as the post-processing scripts + * assume that the address of any data in this section (i.e., symbol names) is + * strictly equivalent to the offset inside the section. + */ +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID + SECTION_PROLOGUE(llext_exports_strtab, 0 (COPY), ) + { + KEEP(*(llext_exports_strtab)) + } +#endif diff --git a/include/zephyr/llext/symbol.h b/include/zephyr/llext/symbol.h index e42dc37c9efa44..b9d5c6138a8935 100644 --- a/include/zephyr/llext/symbol.h +++ b/include/zephyr/llext/symbol.h @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -27,14 +28,27 @@ extern "C" { * Symbols may be named function or global objects that have been exported * for linking. These constant symbols are useful in the base image * as they may be placed in ROM. + * + * @note When updating this structure, make sure to also update the + * 'scripts/build/llext_prepare_exptab.py' build script. */ struct llext_const_symbol { - /** Name of symbol */ - const char *const name; + /** At build time, we always write to 'name'. + * At runtime, which field is used depends + * on CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID. + */ + union { + /** Name of symbol */ + const char *const name; + + /** Symbol Link Identifier */ + const uintptr_t slid; + }; /** Address of symbol */ const void *const addr; }; +BUILD_ASSERT(sizeof(struct llext_const_symbol) == 2 * sizeof(uintptr_t)); /** * @brief Symbols are named memory addresses @@ -75,10 +89,19 @@ struct llext_symtable { * * @param x Symbol to export to extensions */ +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID +#define EXPORT_SYMBOL(x) \ + static const char Z_GENERIC_SECTION("llext_exports_strtab") __used \ + x ## _sym_name[] = STRINGIFY(x); \ + static const STRUCT_SECTION_ITERABLE(llext_const_symbol, x ## _sym) = { \ + .name = x ## _sym_name, .addr = (const void *)&x, \ + } +#else #define EXPORT_SYMBOL(x) \ static const STRUCT_SECTION_ITERABLE(llext_const_symbol, x ## _sym) = { \ .name = STRINGIFY(x), .addr = (const void *)&x, \ } +#endif /** * @brief Exports a symbol from an extension to the base image diff --git a/scripts/build/llext_inject_slids.py b/scripts/build/llext_inject_slids.py new file mode 100755 index 00000000000000..19e87edba93385 --- /dev/null +++ b/scripts/build/llext_inject_slids.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +"""Injects SLIDs in LLEXT ELFs' symbol tables. + +When Kconfig option CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID is enabled, +all imports from the Zephyr kernel & application are resolved using +SLIDs instead of symbol names. This script stores the SLID of all +imported symbols in their associated entry in the ELF symbol table +to allow the LLEXT subsystem to link it properly at runtime. + +Note that this script is idempotent in theory. However, to prevent +any catastrophic problem, the script will abort if the 'st_value' +field of the `ElfX_Sym` structure is found to be non-zero, which is +the case after one invocation. For this reason, in practice, the script +cannot actually be executed twice on the same ELF file. +""" + +import argparse +import logging +import shutil +import sys + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection + +import llext_slidlib + +class LLEXTSymtabPreparator(): + def __init__(self, elf_path, log): + self.log = log + self.elf_path = elf_path + self.elf_fd = open(elf_path, "rb+") + self.elf = ELFFile(self.elf_fd) + + def _find_symtab(self): + supported_symtab_sections = [ + ".symtab", + ".dynsym", + ] + + symtab = None + for section_name in supported_symtab_sections: + symtab = self.elf.get_section_by_name(section_name) + if not isinstance(symtab, SymbolTableSection): + self.log.debug(f"section {section_name} not found.") + else: + self.log.info(f"processing '{section_name}' symbol table...") + self.log.debug(f"(symbol table is at file offset 0x{symtab['sh_offset']:X})") + break + return symtab + + def _find_imports_in_symtab(self, symtab): + i = 0 + imports = [] + for sym in symtab.iter_symbols(): + #Check if symbol is an import + if sym.entry['st_info']['type'] == 'STT_NOTYPE' and \ + sym.entry['st_info']['bind'] == 'STB_GLOBAL' and \ + sym.entry['st_shndx'] == 'SHN_UNDEF': + + self.log.debug(f"found imported symbol '{sym.name}' at index {i}") + imports.append((i, sym)) + + i += 1 + return imports + + def _prepare_inner(self): + #1) Locate the symbol table + symtab = self._find_symtab() + if symtab is None: + self.log.error("no symbol table found in file") + return 1 + + #2) Find imported symbols in symbol table + imports = self._find_imports_in_symtab(symtab) + self.log.info(f"LLEXT has {len(imports)} import(s)") + + #3) Write SLIDs in each symbol's 'st_value' field + def make_stvalue_reader_writer(): + byteorder = "little" if self.elf.little_endian else "big" + if self.elf.elfclass == 32: + sizeof_Elf_Sym = 0x10 #sizeof(Elf32_Sym) + offsetof_st_value = 0x4 #offsetof(Elf32_Sym, st_value) + sizeof_st_value = 0x4 #sizeof(Elf32_Sym.st_value) + else: + sizeof_Elf_Sym = 0x18 + offsetof_st_value = 0x8 + sizeof_st_value = 0x8 + + def seek(symidx): + self.elf_fd.seek( + symtab['sh_offset'] + + symidx * sizeof_Elf_Sym + + offsetof_st_value) + + def reader(symbol_index): + seek(symbol_index) + return int.from_bytes(self.elf_fd.read(sizeof_st_value), byteorder) + + def writer(symbol_index, st_value): + seek(symbol_index) + self.elf_fd.write(int.to_bytes(st_value, sizeof_st_value, byteorder)) + + return reader, writer + + rd_st_val, wr_st_val = make_stvalue_reader_writer() + slid_size = self.elf.elfclass // 8 + + for (index, symbol) in imports: + slid = llext_slidlib.generate_slid(symbol.name, slid_size) + slid_as_str = llext_slidlib.format_slid(slid, slid_size) + msg = f"{symbol.name} -> {slid_as_str}" + + self.log.info(msg) + + # Make sure we're not overwriting something actually important + original_st_value = rd_st_val(index) + if original_st_value != 0: + self.log.error(f"unexpected non-zero st_value for symbol {symbol.name}") + return 1 + + wr_st_val(index, slid) + + return 0 + + def prepare_llext(self): + res = self._prepare_inner() + self.elf_fd.close() + return res + +# Disable duplicate code warning for the code that follows, +# as it is expected for these functions to be similar. +# pylint: disable=duplicate-code +def _parse_args(argv): + """Parse the command line arguments.""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + allow_abbrev=False) + + parser.add_argument("-f", "--elf-file", required=True, + help="LLEXT ELF file to process") + parser.add_argument("-o", "--output-file", + help=("Additional output file where processed ELF " + "will be copied")) + parser.add_argument("-sl", "--slid-listing", + help="write the SLID listing to a file") + parser.add_argument("-v", "--verbose", action="count", + help=("enable verbose output, can be used multiple times " + "to increase verbosity level")) + parser.add_argument("--always-succeed", action="store_true", + help="always exit with a return code of 0, used for testing") + + return parser.parse_args(argv) + +def _init_log(verbose): + """Initialize a logger object.""" + log = logging.getLogger(__file__) + + console = logging.StreamHandler() + console.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) + log.addHandler(console) + + if verbose and verbose > 1: + log.setLevel(logging.DEBUG) + elif verbose and verbose > 0: + log.setLevel(logging.INFO) + else: + log.setLevel(logging.WARNING) + + return log + +def main(argv=None): + args = _parse_args(argv) + + log = _init_log(args.verbose) + + log.info(f"inject_slids_in_llext: {args.elf_file}") + + preparator = LLEXTSymtabPreparator(args.elf_file, log) + + res = preparator.prepare_llext() + + if args.always_succeed: + return 0 + + if res == 0 and args.output_file: + shutil.copy(args.elf_file, args.output_file) + + return res + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/scripts/build/llext_prepare_exptab.py b/scripts/build/llext_prepare_exptab.py new file mode 100755 index 00000000000000..c659709af17e6b --- /dev/null +++ b/scripts/build/llext_prepare_exptab.py @@ -0,0 +1,377 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +""" +Script to prepare the LLEXT exports table of a Zephyr ELF + +This script performs compile-time processing of the LLEXT exports +table for usage at runtime by the LLEXT subsystem code. The table +is a special section filled with 'llext_const_symbol' structures +generated by the EXPORT_SYMBOL macro. + +Currently, the preparatory work consists mostly of sorting the +exports table to allow usage of binary search algorithms at runtime. +If CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID option is enabled, SLIDs +of all exported functions are also injected in the export table by +this script. (In this case, the preparation process is destructive) +""" + +import llext_slidlib + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import Section + +import argparse +import logging +import pathlib +import struct +import sys + +#!!!!! WARNING !!!!! +# +#These constants MUST be kept in sync with the linker scripts +#and the EXPORT_SYMBOL macro located in 'subsys/llext/llext.h'. +#Otherwise, the LLEXT subsystem will be broken! +# +#!!!!! WARNING !!!!! + +LLEXT_EXPORT_TABLE_SECTION_NAME = "llext_const_symbol_area" +LLEXT_EXPORT_NAMES_SECTION_NAME = "llext_exports_strtab" + +def _llext_const_symbol_struct(ptr_size: int, endianness: str): + """ + ptr_size -- Platform pointer size in bytes + endianness -- Platform endianness ('little'/'big') + """ + endspec = "<" if endianness == 'little' else ">" + if ptr_size == 4: + ptrspec = "I" + elif ptr_size == 8: + ptrspec = "Q" + + # struct llext_const_symbol + # contains just two pointers. + lcs_spec = endspec + 2 * ptrspec + return struct.Struct(lcs_spec) + +#ELF Shdr flag applied to the export table section, to indicate +#the section has already been prepared by this script. This is +#mostly a security measure to prevent the script from running +#twice on the same ELF file, which can result in catastrophic +#failures if SLID-based linking is enabled (in this case, the +#preparation process is destructive). +# +#This flag is part of the SHF_MASKOS mask, of which all bits +#are "reserved for operating system-specific semantics". +#See: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html +SHF_LLEXT_PREPARATION_DONE = 0x08000000 + +class SectionDescriptor(): + """ELF Section descriptor + + This is a wrapper class around pyelftools' "Section" object. + """ + def __init__(self, elffile, section_name): + self.name = section_name + self.section = elffile.get_section_by_name(section_name) + if not isinstance(self.section, Section): + raise KeyError(f"section {section_name} not found") + + self.shdr_index = elffile.get_section_index(section_name) + self.shdr_offset = elffile['e_shoff'] + \ + self.shdr_index * elffile['e_shentsize'] + self.size = self.section['sh_size'] + self.flags = self.section['sh_flags'] + self.offset = self.section['sh_offset'] + +class LLEXTExptabManipulator(): + """Class used to wrap the LLEXT export table manipulation.""" + def __init__(self, elf_fd, exptab_file_offset, lcs_struct, exports_count): + self.fd = elf_fd + self.exports_count = exports_count + self.base_offset = exptab_file_offset + self.lcs_struct = lcs_struct + + def _seek_to_sym(self, index): + self.fd.seek(self.base_offset + index * self.lcs_struct.size) + + def __getitem__(self, index): + if not isinstance(index, int): + raise TypeError(f"invalid type {type(index)} for index") + + if index >= self.exports_count: + raise IndexError(f"index {index} is out of bounds (max {self.exports_count})") + + self._seek_to_sym(index) + return self.lcs_struct.unpack(self.fd.read(self.lcs_struct.size)) + + def __setitem__(self, index, item): + if not isinstance(index, int): + raise TypeError(f"invalid type {type(index)} for index") + + if index >= self.exports_count: + raise IndexError(f"index {index} is out of bounds (max {self.exports_count})") + + (addr_or_slid, sym_addr) = item + + self._seek_to_sym(index) + self.fd.write(self.lcs_struct.pack(addr_or_slid, sym_addr)) + +class ZephyrElfExptabPreparator(): + """Prepares the LLEXT export table of a Zephyr ELF. + + Attributes: + elf_path: path to the Zephyr ELF to prepare + log: a logging.Logger object + slid_listing_path: path to the file where SLID listing should be saved + """ + def __init__(self, elf_path: str, log: logging.Logger, slid_listing_path: str | None): + self.elf_path = elf_path + self.elf_fd = open(self.elf_path, 'rb+') + self.elf = ELFFile(self.elf_fd) + self.log = log + + # Lazy-open the SLID listing file to ensure it is only created when necessary + self.slid_listing_path = slid_listing_path + self.slid_listing_fd = None + + def _prepare_exptab_for_slid_linking(self): + """ + IMPLEMENTATION NOTES: + In the linker script, we declare the export names table + as starting at address 0. Thanks to this, all "pointers" + to that section are equal to the offset inside the section. + Also note that symbol names are always NUL-terminated. + + The export table is sorted by SLID in ASCENDING order. + """ + def read_symbol_name(name_ptr): + raw_name = b'' + self.elf_fd.seek(self.expstrtab_section.offset + name_ptr) + + c = self.elf_fd.read(1) + while c != b'\0': + raw_name += c + c = self.elf_fd.read(1) + + return raw_name.decode("utf-8") + + #1) Load the export table + exports_list = [] + for (name_ptr, export_address) in self.exptab_manipulator: + export_name = read_symbol_name(name_ptr) + exports_list.append((export_name, export_address)) + + #2) Generate the SLID for all exports + collided = False + sorted_exptab = dict() + for export_name, export_addr in exports_list: + slid = llext_slidlib.generate_slid(export_name, self.ptrsize) + + collision = sorted_exptab.get(slid) + if collision: + #Don't abort immediately on collision: if there are others, we want to log them all. + self.log.error(f"SLID collision: {export_name} and {collision[0]} have the same SLID 0x{slid:X}") + collided = True + else: + sorted_exptab[slid] = (export_name, export_addr) + + if collided: + return 1 + + #3) Sort the export table (order specified above) + sorted_exptab = dict(sorted(sorted_exptab.items())) + + #4) Write the updated export table to ELF, and dump + #to SLID listing if requested by caller + if self.slid_listing_path: + self.slid_listing_fd = open(self.slid_listing_path, "w") + + def slidlist_write(msg): + if self.slid_listing_fd: + self.slid_listing_fd.write(msg + "\n") + + slidlist_write(f"/* SLID listing generated by {__file__} */") + slidlist_write("//") + slidlist_write("// This file contains the 'SLID -> name' mapping for all") + slidlist_write("// symbols exported to LLEXT by this Zephyr executable.") + slidlist_write("") + + self.log.info("SLID -> export name mapping:") + + i = 0 + for (slid, name_and_symaddr) in sorted_exptab.items(): + slid_as_str = llext_slidlib.format_slid(slid, self.ptrsize) + msg = f"{slid_as_str} -> {name_and_symaddr[0]}" + self.log.info(msg) + slidlist_write(msg) + + self.exptab_manipulator[i] = (slid, name_and_symaddr[1]) + i += 1 + + if self.slid_listing_fd: + self.slid_listing_fd.close() + + return 0 + + def _prepare_exptab_for_str_linking(self): + #TODO: sort the export table by symbol + # name to allow binary search too + # + # Plan of action: + # 1) Locate in which section the names are located + # 2) Load the export table and resolve names + # 3) Sort the exports by name + # WARN: THIS MUST USE THE SAME SORTING RULES + # AS LLEXT CODE OR DICHOTOMIC SEARCH WILL BREAK + # Using a custom sorting function might be required. + # 4) Write back the updated export table + # + # N.B.: reusing part of the code in _prepare_elf_for_slid_linking + # might be possible and desireable. + # + # As of writing, this function will never be called as this script + # is only called if CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID is enabled, + # which makes _prepare_exptab_for_slid_linking be called instead. + # + self.log.warn(f"_prepare_exptab_for_str_linking: do nothing") + return 0 + + def _set_prep_done_shdr_flag(self): + #Offset and size of the 'sh_flags' member of + #the Elf_Shdr structure. The offset does not + #change between ELF32 and ELF64. Size in both + #is equal to pointer size (4 bytes for ELF32, + #8 bytes for ELF64). + SHF_OFFSET = 8 + SHF_SIZE = self.ptrsize + + off = self.exptab_section.shdr_offset + SHF_OFFSET + + #Read existing sh_flags, set the PREPARATION_DONE flag + #and write back the new value. + self.elf_fd.seek(off) + sh_flags = int.from_bytes(self.elf_fd.read(SHF_SIZE), self.endianness) + + sh_flags |= SHF_LLEXT_PREPARATION_DONE + + self.elf_fd.seek(off) + self.elf_fd.write(int.to_bytes(sh_flags, self.ptrsize, self.endianness)) + + def _prepare_inner(self): + # Locate the export table section + try: + self.exptab_section = SectionDescriptor( + self.elf, LLEXT_EXPORT_TABLE_SECTION_NAME) + except KeyError as e: + self.log.error(e.args[0]) + return 1 + + # Abort if the ELF has already been processed + if (self.exptab_section.flags & SHF_LLEXT_PREPARATION_DONE) != 0: + self.log.warning("exptab section flagged with LLEXT_PREPARATION_DONE " + "- not preparing again") + return 0 + + # Get the struct.Struct for export table entry + self.ptrsize = self.elf.elfclass // 8 + self.endianness = 'little' if self.elf.little_endian else 'big' + self.lcs_struct = _llext_const_symbol_struct(self.ptrsize, self.endianness) + + # Verify that the export table size is coherent + if (self.exptab_section.size % self.lcs_struct.size) != 0: + self.log.error(f"export table size (0x{self.exptab_section.size:X}) " + f"not aligned to 'llext_const_symbol' size (0x{self.lcs_struct.size:X})") + return 1 + + # Create the export table manipulator + num_exports = self.exptab_section.size // self.lcs_struct.size + self.exptab_manipulator = LLEXTExptabManipulator( + self.elf_fd, self.exptab_section.offset, self.lcs_struct, num_exports) + + # Attempt to locate the export names section + try: + self.expstrtab_section = SectionDescriptor( + self.elf, LLEXT_EXPORT_NAMES_SECTION_NAME) + except KeyError: + self.expstrtab_section = None + + self.log.debug(f"exports table section at file offset 0x{self.exptab_section.offset:X}") + if self.expstrtab_section: + self.log.debug(f"exports strtab section at file offset 0x{self.expstrtab_section.offset:X}") + else: + self.log.debug("no exports strtab section in ELF") + self.log.info(f"{num_exports} symbols are exported to LLEXTs by this ELF") + + # Perform the export table preparation + if self.expstrtab_section: + res = self._prepare_exptab_for_slid_linking() + else: + res = self._prepare_exptab_for_str_linking() + + if res == 0: # Add the "prepared" flag to export table section + self._set_prep_done_shdr_flag() + + def prepare_elf(self): + res = self._prepare_inner() + self.elf_fd.close() + return res + +# pylint: disable=duplicate-code +def _parse_args(argv): + """Parse the command line arguments.""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + allow_abbrev=False) + + parser.add_argument("-f", "--elf-file", default=pathlib.Path("build", "zephyr", "zephyr.elf"), + help="ELF file to process") + parser.add_argument("-sl", "--slid-listing", + help=("write the SLID listing to a file (only useful" + "when CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID is enabled) ")) + parser.add_argument("-v", "--verbose", action="count", + help=("enable verbose output, can be used multiple times " + "to increase verbosity level")) + parser.add_argument("--always-succeed", action="store_true", + help="always exit with a return code of 0, used for testing") + + return parser.parse_args(argv) + +def _init_log(verbose): + """Initialize a logger object.""" + log = logging.getLogger(__file__) + + console = logging.StreamHandler() + console.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) + log.addHandler(console) + + if verbose and verbose > 1: + log.setLevel(logging.DEBUG) + elif verbose and verbose > 0: + log.setLevel(logging.INFO) + else: + log.setLevel(logging.WARNING) + + return log + +def main(argv=None): + args = _parse_args(argv) + + log = _init_log(args.verbose) + + log.info(f"prepare_llext_exptab: {args.elf_file}") + + preparator = ZephyrElfExptabPreparator(args.elf_file, log, args.slid_listing) + + res = preparator.prepare_elf() + + if args.always_succeed: + return 0 + + return res + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/scripts/build/llext_slidlib.py b/scripts/build/llext_slidlib.py new file mode 100755 index 00000000000000..99157c526dcc3f --- /dev/null +++ b/scripts/build/llext_slidlib.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +""" +This file implements the Symbol Link Identifer (SLID) +generation code, for use by the LLEXT subsystem. +SLID-based linking is enabled by the Kconfig +option 'CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID'. + +When executed as a script, this file can be used as +an interactive prompt to calculate the SLID of arbitrary +symbols, which can be useful for debugging purposes. + +IMPLEMENTATION NOTES: + Currently, SLIDs are generated by taking the first + [pointer size] bytes of the symbol name's SHA-256 + hash, taken in big-endian order. + + This ordering provides one advantage: the 32-bit + SLID for an export is present in the top 32 bits of + the 64-bit SLID for the same export. +""" + +from hashlib import sha256 + +def generate_slid(symbol_name: str, slid_size: int) -> int: + """ + Generates the Symbol Link Identifier (SLID) for a symbol. + + symbol_name: Name of the symbol for which to generate a SLID + slid_side: Size of the SLID in bytes (4/8) + """ + if slid_size not in (4, 8): + raise AssertionError(f"Invalid SLID size {slid_size}") + + m = sha256() + m.update(symbol_name.encode("utf-8")) + hash = m.digest() + return int.from_bytes(hash[0:slid_size], byteorder='big', signed=False) + +def format_slid(slid: int, slid_size: int) -> str: + if slid_size == 4: + fmt = f"0x{slid:08X}" + elif slid_size == 8: + fmt = f"0x{slid:016X}" + return fmt + +def repl(): + while True: + sym_name = input("Symbol name? ") + slid32 = generate_slid(sym_name, 4) + slid64 = generate_slid(sym_name, 8) + print(f" 32-bit SLID for '{sym_name}': {format_slid(slid32, 4)}") + print(f" 64-bit SLID for '{sym_name}': {format_slid(slid64, 8)}") + print() + +if __name__ == "__main__": + print("LLEXT SLID calculation REPL") + print("Press ^C to exit.") + try: + repl() + except KeyboardInterrupt: + print() diff --git a/soc/andestech/ae350/linker.ld b/soc/andestech/ae350/linker.ld index 9098aa2072fab8..9419856a499cde 100644 --- a/soc/andestech/ae350/linker.ld +++ b/soc/andestech/ae350/linker.ld @@ -92,6 +92,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * The .plt and .iplt are here according to * 'riscv32-zephyr-elf-ld --verbose', before text section. diff --git a/soc/cdns/dc233c/include/xtensa-dc233c.ld b/soc/cdns/dc233c/include/xtensa-dc233c.ld index 87ad18b54246c5..6ca62979633233 100644 --- a/soc/cdns/dc233c/include/xtensa-dc233c.ld +++ b/soc/cdns/dc233c/include/xtensa-dc233c.ld @@ -113,6 +113,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + #ifdef CONFIG_GEN_ISR_TABLES #include #endif diff --git a/soc/cdns/xtensa_sample_controller/include/xtensa-sample-controller.ld b/soc/cdns/xtensa_sample_controller/include/xtensa-sample-controller.ld index 842ec8141f4a82..bd93a0861b4794 100644 --- a/soc/cdns/xtensa_sample_controller/include/xtensa-sample-controller.ld +++ b/soc/cdns/xtensa_sample_controller/include/xtensa-sample-controller.ld @@ -177,6 +177,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + #ifdef CONFIG_GEN_ISR_TABLES #include #endif diff --git a/soc/espressif/esp32/default.ld b/soc/espressif/esp32/default.ld index 338a90b99643be..4e07ecf46de358 100644 --- a/soc/espressif/esp32/default.ld +++ b/soc/espressif/esp32/default.ld @@ -152,6 +152,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT + #include +#endif + /* --- RTC BEGIN --- */ /* RTC fast memory holds RTC wake stub code, diff --git a/soc/espressif/esp32/default_appcpu.ld b/soc/espressif/esp32/default_appcpu.ld index a28399f57c4fd9..57a35c474509a1 100644 --- a/soc/espressif/esp32/default_appcpu.ld +++ b/soc/espressif/esp32/default_appcpu.ld @@ -55,6 +55,10 @@ SECTIONS { #include +#ifdef CONFIG_LLEXT +#include +#endif + _image_iram_start = LOADADDR(.iram0.vectors); _image_iram_size = LOADADDR(_TEXT_SECTION_NAME) + SIZEOF(_TEXT_SECTION_NAME) - _image_iram_start; _image_iram_vaddr = ADDR(.iram0.vectors); diff --git a/soc/espressif/esp32c3/default.ld b/soc/espressif/esp32c3/default.ld index 17e883373553ab..849f568f1aeb93 100644 --- a/soc/espressif/esp32c3/default.ld +++ b/soc/espressif/esp32c3/default.ld @@ -129,6 +129,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT + #include +#endif + /* --- START OF RTC --- */ .rtc.text : diff --git a/soc/espressif/esp32s2/default.ld b/soc/espressif/esp32s2/default.ld index 0799af2ea4adf8..03c1d75a9278f5 100644 --- a/soc/espressif/esp32s2/default.ld +++ b/soc/espressif/esp32s2/default.ld @@ -136,6 +136,10 @@ SECTIONS /* Virtual non-loadable sections */ #include +#ifdef CONFIG_LLEXT +#include +#endif + /* --- START OF RTC --- */ /* RTC fast memory holds RTC wake stub code, diff --git a/soc/espressif/esp32s3/default.ld b/soc/espressif/esp32s3/default.ld index 93c9c3044b98c0..17277f5ebccabd 100644 --- a/soc/espressif/esp32s3/default.ld +++ b/soc/espressif/esp32s3/default.ld @@ -135,6 +135,10 @@ SECTIONS /* Virtual non-loadable sections */ #include +#ifdef CONFIG_LLEXT +#include +#endif + /* --- START OF RTC --- */ /* RTC fast memory holds RTC wake stub code */ diff --git a/soc/espressif/esp32s3/default_appcpu.ld b/soc/espressif/esp32s3/default_appcpu.ld index d5e0e2fe3e9cda..efc684161b547e 100644 --- a/soc/espressif/esp32s3/default_appcpu.ld +++ b/soc/espressif/esp32s3/default_appcpu.ld @@ -38,6 +38,10 @@ SECTIONS { #include + #ifdef CONFIG_LLEXT + #include + #endif + /* Send .iram0 code to iram */ .iram0.vectors : ALIGN(4) { diff --git a/soc/infineon/cat1b/cyw20829/linker.ld b/soc/infineon/cat1b/cyw20829/linker.ld index 11b36b51170541..efe1dffa603fab 100644 --- a/soc/infineon/cat1b/cyw20829/linker.ld +++ b/soc/infineon/cat1b/cyw20829/linker.ld @@ -104,6 +104,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/soc/intel/intel_adsp/ace/ace-link.ld b/soc/intel/intel_adsp/ace/ace-link.ld index 454893055e1712..b259c842995cc2 100644 --- a/soc/intel/intel_adsp/ace/ace-link.ld +++ b/soc/intel/intel_adsp/ace/ace-link.ld @@ -490,4 +490,8 @@ SECTIONS { #ifdef CONFIG_GEN_ISR_TABLES #include #endif + +#ifdef CONFIG_LLEXT +#include +#endif } diff --git a/soc/intel/intel_adsp/cavs/include/xtensa-cavs-linker.ld b/soc/intel/intel_adsp/cavs/include/xtensa-cavs-linker.ld index e9ecbe2ba1b678..03109061fc6ad3 100644 --- a/soc/intel/intel_adsp/cavs/include/xtensa-cavs-linker.ld +++ b/soc/intel/intel_adsp/cavs/include/xtensa-cavs-linker.ld @@ -503,4 +503,8 @@ SECTIONS { #ifdef CONFIG_GEN_ISR_TABLES #include #endif + +#ifdef CONFIG_LLEXT +#include +#endif } diff --git a/soc/ite/ec/it8xxx2/linker.ld b/soc/ite/ec/it8xxx2/linker.ld index 3ad9bd21df3a0f..8143d789d20055 100644 --- a/soc/ite/ec/it8xxx2/linker.ld +++ b/soc/ite/ec/it8xxx2/linker.ld @@ -91,6 +91,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * The .plt and .iplt are here according to * 'riscv32-zephyr-elf-ld --verbose', before text section. diff --git a/soc/nxp/imx/imx8/adsp/linker.ld b/soc/nxp/imx/imx8/adsp/linker.ld index 52d3a46b2381a9..caaaf8e60d1f31 100644 --- a/soc/nxp/imx/imx8/adsp/linker.ld +++ b/soc/nxp/imx/imx8/adsp/linker.ld @@ -173,6 +173,10 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/nxp/imx/imx8m/adsp/linker.ld b/soc/nxp/imx/imx8m/adsp/linker.ld index 97d969d476fcbd..6ca8e72982e7b4 100644 --- a/soc/nxp/imx/imx8m/adsp/linker.ld +++ b/soc/nxp/imx/imx8m/adsp/linker.ld @@ -179,6 +179,10 @@ SECTIONS #endif #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/nxp/imx/imx8ulp/adsp/linker.ld b/soc/nxp/imx/imx8ulp/adsp/linker.ld index 4b5aec29742a73..96bd687917fbec 100644 --- a/soc/nxp/imx/imx8ulp/adsp/linker.ld +++ b/soc/nxp/imx/imx8ulp/adsp/linker.ld @@ -173,6 +173,10 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/nxp/imx/imx8x/adsp/linker.ld b/soc/nxp/imx/imx8x/adsp/linker.ld index 52d3a46b2381a9..caaaf8e60d1f31 100644 --- a/soc/nxp/imx/imx8x/adsp/linker.ld +++ b/soc/nxp/imx/imx8x/adsp/linker.ld @@ -173,6 +173,10 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/nxp/imx/imx9/a55/linker.ld b/soc/nxp/imx/imx9/a55/linker.ld index 102d9f1b0445d8..53982a309c8607 100644 --- a/soc/nxp/imx/imx9/a55/linker.ld +++ b/soc/nxp/imx/imx9/a55/linker.ld @@ -71,6 +71,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/soc/nxp/imxrt/imxrt5xx/f1/linker.ld b/soc/nxp/imxrt/imxrt5xx/f1/linker.ld index adc8b87fb62136..de1e89846530be 100644 --- a/soc/nxp/imxrt/imxrt5xx/f1/linker.ld +++ b/soc/nxp/imxrt/imxrt5xx/f1/linker.ld @@ -134,6 +134,10 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/openisa/rv32m1/linker.ld b/soc/openisa/rv32m1/linker.ld index 784ba791722bf6..b81a77868a9087 100644 --- a/soc/openisa/rv32m1/linker.ld +++ b/soc/openisa/rv32m1/linker.ld @@ -87,6 +87,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + SECTION_PROLOGUE(.plt,,) { *(.plt) diff --git a/soc/st/stm32/stm32mp1x/linker.ld b/soc/st/stm32/stm32mp1x/linker.ld index 7f9a84501ef115..83f3511b7088ef 100644 --- a/soc/st/stm32/stm32mp1x/linker.ld +++ b/soc/st/stm32/stm32mp1x/linker.ld @@ -13,6 +13,11 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif + #ifdef CONFIG_OPENAMP_RSC_TABLE SECTION_PROLOGUE(.resource_table,, SUBALIGN(4)) diff --git a/subsys/llext/Kconfig b/subsys/llext/Kconfig index 8984cb3ca3988c..4ad2aca1c03794 100644 --- a/subsys/llext/Kconfig +++ b/subsys/llext/Kconfig @@ -66,6 +66,21 @@ config LLEXT_STORAGE_WRITABLE Select if LLEXT storage is writable, i.e. if extensions are stored in RAM and can be modified in place +config LLEXT_EXPORT_BUILTINS_BY_SLID + bool "Export built-in symbols to llexts via SLIDs" + help + When enabled, symbols exported from the Zephyr kernel + or application (via EXPORT_SYMBOL) are linked to LLEXTs + via Symbol Link Identifiers (SLIDs) instead of name. + + Enabling this option provides a huge size reduction, + makes the linking process faster and provides more + confidentiality, as exported symbol names are dropped + from the binary. However, it can make LLEXT debugging + harder and prevents usage of 'llext_find_sym' to look + up symbols from the built-in table by name. It also + requires the LLEXTs to be post-processed after build. + module = LLEXT module-str = llext source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index 856b322c49ae14..a647ac3bc27b04 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -24,6 +24,12 @@ LOG_MODULE_REGISTER(llext, CONFIG_LLEXT_LOG_LEVEL); #define LLEXT_PAGE_SIZE 32 #endif +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID +#define SYM_NAME_OR_SLID(name, slid) ((const char *)slid) +#else +#define SYM_NAME_OR_SLID(name, slid) name +#endif + K_HEAP_DEFINE(llext_heap, CONFIG_LLEXT_HEAP_SIZE * 1024); static const char ELF_MAGIC[] = {0x7f, 'E', 'L', 'F'}; @@ -118,11 +124,27 @@ const void *llext_find_sym(const struct llext_symtable *sym_table, const char *s { if (sym_table == NULL) { /* Built-in symbol table */ +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID + /* 'sym_name' is actually a SLID to search for */ + uintptr_t slid = (uintptr_t)sym_name; + + /* TODO: perform a binary search instead of linear. + * Note that - as of writing - the llext_const_symbol_area + * section is sorted in ascending SLID order. + * (see scripts/build/llext_prepare_exptab.py) + */ + STRUCT_SECTION_FOREACH(llext_const_symbol, sym) { + if (slid == sym->slid) { + return sym->addr; + } + } +#else STRUCT_SECTION_FOREACH(llext_const_symbol, sym) { if (strcmp(sym->name, sym_name) == 0) { return sym->addr; } } +#endif } else { /* find symbols in module */ for (size_t i = 0; i < sym_table->sym_cnt; i++) { @@ -728,7 +750,8 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, switch (stb) { case STB_GLOBAL: - link_addr = llext_find_sym(NULL, name); + link_addr = llext_find_sym(NULL, + SYM_NAME_OR_SLID(name, sym_tbl.st_value)); if (!link_addr) link_addr = llext_find_sym(&ext->sym_tab, name); @@ -864,7 +887,8 @@ static int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local link_addr = 0; } else if (sym.st_shndx == SHN_UNDEF) { /* If symbol is undefined, then we need to look it up */ - link_addr = (uintptr_t)llext_find_sym(NULL, name); + link_addr = (uintptr_t)llext_find_sym(NULL, + SYM_NAME_OR_SLID(name, sym.st_value)); if (link_addr == 0) { LOG_ERR("Undefined symbol with no entry in " diff --git a/tests/subsys/llext/simple/src/test_llext_simple.c b/tests/subsys/llext/simple/src/test_llext_simple.c index 68b318f5e1c80c..91a3c3e6f3d2a0 100644 --- a/tests/subsys/llext/simple/src/test_llext_simple.c +++ b/tests/subsys/llext/simple/src/test_llext_simple.c @@ -24,6 +24,20 @@ LOG_MODULE_REGISTER(test_llext_simple); #define LLEXT_CONST const #endif +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID +#define LLEXT_FIND_BUILTIN_SYM(symbol_name) llext_find_sym(NULL, symbol_name ## _SLID) + +#ifdef CONFIG_64BIT +#define printk_SLID ((const char *)0x87B3105268827052ull) +#define z_impl_ext_syscall_fail_SLID ((const char *)0xD58BC0E7C64CD965ull) +#else +#define printk_SLID ((const char *)0x87B31052ull) +#define z_impl_ext_syscall_fail_SLID ((const char *)0xD58BC0E7ull) +#endif +#else +#define LLEXT_FIND_BUILTIN_SYM(symbol_name) llext_find_sym(NULL, # symbol_name) +#endif + struct llext_test { const char *name; bool try_userspace; @@ -271,7 +285,7 @@ ZTEST(llext, test_pre_located) */ ZTEST(llext, test_printk_exported) { - const void * const printk_fn = llext_find_sym(NULL, "printk"); + const void * const printk_fn = LLEXT_FIND_BUILTIN_SYM(printk); zassert_equal(printk_fn, printk, "printk should be an exported symbol"); } @@ -282,8 +296,9 @@ ZTEST(llext, test_printk_exported) */ ZTEST(llext, test_ext_syscall_fail) { - const void * const esf_fn = llext_find_sym(NULL, - "z_impl_ext_syscall_fail"); + const void * const esf_fn = LLEXT_FIND_BUILTIN_SYM(z_impl_ext_syscall_fail); + + zassert_not_null(esf_fn, "est_fn should not be NULL"); zassert_is_null(*(uintptr_t **)esf_fn, NULL, "ext_syscall_fail should be NULL"); diff --git a/tests/subsys/llext/simple/testcase.yaml b/tests/subsys/llext/simple/testcase.yaml index 6325bd51425c97..8a3aca97037d7b 100644 --- a/tests/subsys/llext/simple/testcase.yaml +++ b/tests/subsys/llext/simple/testcase.yaml @@ -80,3 +80,71 @@ tests: - CONFIG_USERSPACE=y - CONFIG_MODULES=y - CONFIG_LLEXT_TEST_HELLO=m + llext.simple.readonly_slid_linking: + arch_exclude: xtensa # for now + filter: not CONFIG_MPU and not CONFIG_MMU and not CONFIG_SOC_SERIES_S32ZE + extra_configs: + - arch:arm:CONFIG_ARM_MPU=n + - CONFIG_LLEXT_STORAGE_WRITABLE=n + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.readonly_mpu_slid_linking: + min_ram: 128 + arch_exclude: xtensa # for now + filter: CONFIG_ARCH_HAS_USERSPACE + extra_configs: + - CONFIG_USERSPACE=y + - CONFIG_LLEXT_STORAGE_WRITABLE=n + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.writable_slid_linking: + filter: not CONFIG_MPU and not CONFIG_MMU and not CONFIG_SOC_SERIES_S32ZE + extra_configs: + - arch:arm:CONFIG_ARM_MPU=n + - CONFIG_LLEXT_STORAGE_WRITABLE=y + llext.simple.modules_enabled_writable_slid_linking: + filter: not CONFIG_MPU and not CONFIG_MMU + platform_key: + - simulation + - arch + platform_exclude: + - qemu_cortex_a9 # MMU + extra_configs: + - arch:arm:CONFIG_ARM_MPU=n + - CONFIG_MODULES=y + - CONFIG_LLEXT_STORAGE_WRITABLE=y + - CONFIG_LLEXT_TEST_HELLO=m + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.modules_enabled_writable_relocatable_slid_linking: + arch_exclude: arm arm64 + filter: not CONFIG_MPU and not CONFIG_MMU + integration_platforms: + - qemu_xtensa + extra_configs: + - CONFIG_MODULES=y + - CONFIG_LLEXT_STORAGE_WRITABLE=y + - CONFIG_LLEXT_TYPE_ELF_RELOCATABLE=y + - CONFIG_LLEXT_TEST_HELLO=m + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.modules_enabled_readonly_slid_linking: + filter: not CONFIG_MPU and not CONFIG_MMU + arch_exclude: xtensa # for now + platform_key: + - simulation + - arch + platform_exclude: + - qemu_cortex_a9 # MMU + extra_configs: + - arch:arm:CONFIG_ARM_MPU=n + - CONFIG_MODULES=y + - CONFIG_LLEXT_TEST_HELLO=m + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.modules_enabled_readonly_mpu_slid_linking: + filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: xtensa # for now + platform_key: + - simulation + - arch + extra_configs: + - CONFIG_USERSPACE=y + - CONFIG_MODULES=y + - CONFIG_LLEXT_TEST_HELLO=m + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y From 912a581a9572ea448e7e6d6b4c0b05b556fc2b67 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Thu, 15 Feb 2024 15:12:10 +0100 Subject: [PATCH 010/981] drivers/led: add IS31FL3194 LED driver Add support for the IS31FL3194 3-channel LED driver. This driver can be configured to handle its outputs as either a single RGB LED or (up to) three independent LEDs. Signed-off-by: Luca Burelli --- drivers/led/CMakeLists.txt | 1 + drivers/led/Kconfig | 1 + drivers/led/Kconfig.is31fl3194 | 11 + drivers/led/is31fl3194.c | 359 ++++++++++++++++++++++++++ dts/bindings/led/issi,is31fl3194.yaml | 74 ++++++ 5 files changed, 446 insertions(+) create mode 100644 drivers/led/Kconfig.is31fl3194 create mode 100644 drivers/led/is31fl3194.c create mode 100644 dts/bindings/led/issi,is31fl3194.yaml diff --git a/drivers/led/CMakeLists.txt b/drivers/led/CMakeLists.txt index c3d90d0ba06ff4..09ea5e202fdf53 100644 --- a/drivers/led/CMakeLists.txt +++ b/drivers/led/CMakeLists.txt @@ -18,6 +18,7 @@ zephyr_library_sources_ifdef(CONFIG_NCP5623 ncp5623.c) zephyr_library_sources_ifdef(CONFIG_PCA9633 pca9633.c) zephyr_library_sources_ifdef(CONFIG_TLC59108 tlc59108.c) zephyr_library_sources_ifdef(CONFIG_IS31FL3733 is31fl3733.c) +zephyr_library_sources_ifdef(CONFIG_IS31FL3194 is31fl3194.c) zephyr_library_sources_ifdef(CONFIG_LED_SHELL led_shell.c) diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index 7808a1013ae9cf..26bf49cd5e2aef 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -40,5 +40,6 @@ source "drivers/led/Kconfig.pwm" source "drivers/led/Kconfig.tlc59108" source "drivers/led/Kconfig.xec" source "drivers/led/Kconfig.is31fl3733" +source "drivers/led/Kconfig.is31fl3194" endif # LED diff --git a/drivers/led/Kconfig.is31fl3194 b/drivers/led/Kconfig.is31fl3194 new file mode 100644 index 00000000000000..42166805a1d16f --- /dev/null +++ b/drivers/led/Kconfig.is31fl3194 @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Arduino SA +# SPDX-License-Identifier: Apache-2.0 + +config IS31FL3194 + bool "IS31FL3194 LED driver" + default y + depends on DT_HAS_ISSI_IS31FL3194_ENABLED + select I2C + help + Enable LED driver for Lumissil Microsystems (a division of ISSI) + IS31FL3194. This chip supports one RGB LED or 3 independent LEDs. diff --git a/drivers/led/is31fl3194.c b/drivers/led/is31fl3194.c new file mode 100644 index 00000000000000..5b0c34ebf571c0 --- /dev/null +++ b/drivers/led/is31fl3194.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT issi_is31fl3194 + +/** + * @file + * @brief IS31FL3194 LED driver + * + * The IS31FL3194 is a 3-channel LED driver that communicates over I2C. + */ + +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(is31fl3194, CONFIG_LED_LOG_LEVEL); + +#define IS31FL3194_PROD_ID_REG 0x00 +#define IS31FL3194_CONF_REG 0x01 +#define IS31FL3194_CURRENT_REG 0x03 +#define IS31FL3194_OUT1_REG 0x10 +#define IS31FL3194_OUT2_REG 0x21 +#define IS31FL3194_OUT3_REG 0x32 +#define IS31FL3194_UPDATE_REG 0x40 + +#define IS31FL3194_PROD_ID_VAL 0xce +#define IS31FL3194_CONF_ENABLE 0x01 +#define IS31FL3194_UPDATE_VAL 0xc5 + +#define IS31FL3194_CHANNEL_COUNT 3 + +static const uint8_t led_channels[] = { + IS31FL3194_OUT1_REG, + IS31FL3194_OUT2_REG, + IS31FL3194_OUT3_REG +}; + +struct is31fl3194_config { + struct i2c_dt_spec bus; + uint8_t num_leds; + const struct led_info *led_infos; + const uint8_t *current_limits; +}; + +static const struct led_info *is31fl3194_led_to_info(const struct is31fl3194_config *config, + uint32_t led) +{ + if (led < config->num_leds) { + return &config->led_infos[led]; + } + + return NULL; +} + +static int is31fl3194_get_info(const struct device *dev, + uint32_t led, + const struct led_info **info_out) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = is31fl3194_led_to_info(config, led); + + if (info == NULL) { + return -EINVAL; + } + + *info_out = info; + return 0; +} + +static int is31fl3194_set_color(const struct device *dev, uint32_t led, uint8_t num_colors, + const uint8_t *color) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = is31fl3194_led_to_info(config, led); + int ret; + + if (info == NULL) { + return -ENODEV; + } + + if (info->num_colors != 3) { + return -ENOTSUP; + } + + if (num_colors != 3) { + return -EINVAL; + } + + for (int i = 0; i < 3; i++) { + uint8_t value; + + switch (info->color_mapping[i]) { + case LED_COLOR_ID_RED: + value = color[0]; + break; + case LED_COLOR_ID_GREEN: + value = color[1]; + break; + case LED_COLOR_ID_BLUE: + value = color[2]; + break; + default: + /* unreachable: mapping already tested in is31fl3194_check_config */ + continue; + } + + ret = i2c_reg_write_byte_dt(&config->bus, led_channels[i], value); + if (ret != 0) { + break; + } + } + + if (ret == 0) { + ret = i2c_reg_write_byte_dt(&config->bus, + IS31FL3194_UPDATE_REG, + IS31FL3194_UPDATE_VAL); + } + + if (ret != 0) { + LOG_ERR("%s: LED write failed: %d", dev->name, ret); + } + + return ret; +} + +static int is31fl3194_set_brightness(const struct device *dev, uint32_t led, uint8_t value) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = is31fl3194_led_to_info(config, led); + int ret = 0; + + if (info == NULL) { + return -ENODEV; + } + + if (info->num_colors != 1) { + return -ENOTSUP; + } + + if (value > 100) { + return -EINVAL; + } + + /* Rescale 0..100 to 0..255 */ + value = value * 255 / 100; + + ret = i2c_reg_write_byte_dt(&config->bus, led_channels[led], value); + if (ret == 0) { + ret = i2c_reg_write_byte_dt(&config->bus, + IS31FL3194_UPDATE_REG, + IS31FL3194_UPDATE_VAL); + } + + if (ret != 0) { + LOG_ERR("%s: LED write failed", dev->name); + } + + return ret; +} + +static inline int is31fl3194_led_on(const struct device *dev, uint32_t led) +{ + return is31fl3194_set_brightness(dev, led, 100); +} + +static inline int is31fl3194_led_off(const struct device *dev, uint32_t led) +{ + return is31fl3194_set_brightness(dev, led, 0); +} + +/* + * Counts red, green, blue channels; returns true if color_id is valid + * and no more than one channel maps to the same color + */ +static bool is31fl3194_count_colors(const struct device *dev, + uint8_t color_id, uint8_t *rgb_counts) +{ + bool ret = false; + + switch (color_id) { + case LED_COLOR_ID_RED: + ret = (++rgb_counts[0] == 1); + break; + case LED_COLOR_ID_GREEN: + ret = (++rgb_counts[1] == 1); + break; + case LED_COLOR_ID_BLUE: + ret = (++rgb_counts[2] == 1); + break; + } + + if (!ret) { + LOG_ERR("%s: invalid color %d (duplicate or not RGB)", + dev->name, color_id); + } + + return ret; +} + +static int is31fl3194_check_config(const struct device *dev) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info; + uint8_t rgb_counts[3] = { 0 }; + uint8_t i; + + switch (config->num_leds) { + case 1: + /* check that it is a three-channel LED */ + info = &config->led_infos[0]; + + if (info->num_colors != 3) { + LOG_ERR("%s: invalid number of colors %d " + "(must be 3 for RGB LED)", + dev->name, info->num_colors); + return -EINVAL; + } + + for (i = 0; i < 3; i++) { + if (!is31fl3194_count_colors(dev, info->color_mapping[i], rgb_counts)) { + return -EINVAL; + } + + } + break; + case 3: + /* check that each LED is single-color */ + for (i = 0; i < 3; i++) { + info = &config->led_infos[i]; + + if (info->num_colors != 1) { + LOG_ERR("%s: invalid number of colors %d " + "(must be 1 when defining multiple LEDs)", + dev->name, info->num_colors); + return -EINVAL; + } + + if (!is31fl3194_count_colors(dev, info->color_mapping[0], rgb_counts)) { + return -EINVAL; + } + } + break; + default: + LOG_ERR("%s: invalid number of LEDs %d (must be 1 or 3)", + dev->name, config->num_leds); + return -EINVAL; + } + + return 0; +} + +static int is31fl3194_init(const struct device *dev) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = NULL; + int i, ret; + uint8_t prod_id, band; + uint8_t current_reg = 0; + + ret = is31fl3194_check_config(dev); + if (ret != 0) { + return ret; + } + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("%s: I2C device not ready", dev->name); + return -ENODEV; + } + + ret = i2c_reg_read_byte_dt(&config->bus, IS31FL3194_PROD_ID_REG, &prod_id); + if (ret != 0) { + LOG_ERR("%s: failed to read product ID", dev->name); + return ret; + } + + if (prod_id != IS31FL3194_PROD_ID_VAL) { + LOG_ERR("%s: invalid product ID 0x%02x (expected 0x%02x)", dev->name, prod_id, + IS31FL3194_PROD_ID_VAL); + return -ENODEV; + } + + /* calc current limit register value */ + info = &config->led_infos[0]; + if (info->num_colors == IS31FL3194_CHANNEL_COUNT) { + /* one RGB LED: set all channels to the same current limit */ + band = (config->current_limits[0] / 10) - 1; + for (i = 0; i < IS31FL3194_CHANNEL_COUNT; i++) { + current_reg |= band << (2 * i); + } + } else { + /* single-channel LEDs: independent limits */ + for (i = 0; i < config->num_leds; i++) { + band = (config->current_limits[i] / 10) - 1; + current_reg |= band << (2 * i); + } + } + + ret = i2c_reg_write_byte_dt(&config->bus, IS31FL3194_CURRENT_REG, current_reg); + if (ret != 0) { + LOG_ERR("%s: failed to set current limit", dev->name); + return ret; + } + + /* enable device */ + return i2c_reg_write_byte_dt(&config->bus, IS31FL3194_CONF_REG, IS31FL3194_CONF_ENABLE); +} + +static const struct led_driver_api is31fl3194_led_api = { + .set_brightness = is31fl3194_set_brightness, + .on = is31fl3194_led_on, + .off = is31fl3194_led_off, + .get_info = is31fl3194_get_info, + .set_color = is31fl3194_set_color, +}; + +#define COLOR_MAPPING(led_node_id) \ + static const uint8_t color_mapping_##led_node_id[] = \ + DT_PROP(led_node_id, color_mapping); + +#define LED_INFO(led_node_id) \ + { \ + .label = DT_PROP(led_node_id, label), \ + .num_colors = DT_PROP_LEN(led_node_id, color_mapping), \ + .color_mapping = color_mapping_##led_node_id, \ + }, + +#define LED_CURRENT(led_node_id) \ + DT_PROP(led_node_id, current_limit), + +#define IS31FL3194_DEFINE(id) \ + \ + DT_INST_FOREACH_CHILD(id, COLOR_MAPPING) \ + \ + static const struct led_info is31fl3194_leds_##id[] = \ + { DT_INST_FOREACH_CHILD(id, LED_INFO) }; \ + static const uint8_t is31fl3194_currents_##id[] = \ + { DT_INST_FOREACH_CHILD(id, LED_CURRENT) }; \ + BUILD_ASSERT(ARRAY_SIZE(is31fl3194_leds_##id) > 0, \ + "No LEDs defined for " #id); \ + \ + static const struct is31fl3194_config is31fl3194_config_##id = { \ + .bus = I2C_DT_SPEC_INST_GET(id), \ + .num_leds = ARRAY_SIZE(is31fl3194_leds_##id), \ + .led_infos = is31fl3194_leds_##id, \ + .current_limits = is31fl3194_currents_##id, \ + }; \ + DEVICE_DT_INST_DEFINE(id, &is31fl3194_init, NULL, NULL, \ + &is31fl3194_config_##id, POST_KERNEL, \ + CONFIG_LED_INIT_PRIORITY, &is31fl3194_led_api); + +DT_INST_FOREACH_STATUS_OKAY(IS31FL3194_DEFINE) diff --git a/dts/bindings/led/issi,is31fl3194.yaml b/dts/bindings/led/issi,is31fl3194.yaml new file mode 100644 index 00000000000000..4d07a36d7a4aa9 --- /dev/null +++ b/dts/bindings/led/issi,is31fl3194.yaml @@ -0,0 +1,74 @@ +# Copyright (c) 2024 Arduino SA +# SPDX-License-Identifier: Apache-2.0 + +description: | + IS31FL3194 3-channel LED driver with programmable pattern sequencing + + This driver supports single-channel and RGB LEDs. For single channel LEDs, + the led_set_brightness() API can be used to set the brightness of each LED. + For RGB LEDs, the led_set_color() API can be used to set the red, green and + blue components; the driver takes care of routing to the outputs described + by the color-mapping property. + + The LED_SHELL application can be used for testing. + + The following defines a single RGB LED in the is31fl3194 DT node: + + is31fl3194@53 { + compatible = "issi,is31fl3194"; + reg = <0x53>; + + led_0 { + label = "RGB LED"; + color-mapping = + , + , + ; + }; + }; + + The following example defines three single-channel LEDs in the is31fl3194 DT node: + + is31fl3194@53 { + compatible = "issi,is31fl3194"; + reg = <0x53>; + + led_0 { + label = "RED LED"; + color-mapping = ; + }; + + led_1 { + label = "GREEN LED"; + color-mapping = ; + }; + + led_2 { + label = "BLUE LED"; + color-mapping = ; + }; + }; + + +compatible: "issi,is31fl3194" + +include: ["i2c-device.yaml", "led-controller.yaml"] + +child-binding: + properties: + label: + required: true + + color-mapping: + required: true + + current-limit: + type: int + enum: + - 10 + - 20 + - 30 + - 40 + required: true + description: | + The current limit for the LED in mA. From 5fea5c4358f06e72d71aeec46938820be4a3bfc5 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 20 Feb 2024 18:04:11 +0100 Subject: [PATCH 011/981] arduino_nicla_sense_me: add RGB LED support to the device tree This patch enables the user to control the RGB LED on the Arduino Nicla Sense ME board. The RGB LED is controlled by the IS31FL3194 LED driver and is connected to the I2C0 bus. Signed-off-by: Luca Burelli --- .../nicla_sense_me/arduino_nicla_sense_me.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts b/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts index 2329853a1a3bb6..87d1affecd604a 100644 --- a/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts +++ b/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts @@ -8,6 +8,7 @@ #include #include "arduino_nicla_sense_me-pinctrl.dtsi" #include +#include / { model = "Arduino Nicla Sense ME"; @@ -73,6 +74,18 @@ pinctrl-0 = <&i2c0_default>; pinctrl-1 = <&i2c0_sleep>; pinctrl-names = "default", "sleep"; + + is31fl3194@53 { + compatible = "issi,is31fl3194"; + reg = <0x53>; + led_rgb { + label = "RGB LED"; + color-mapping = , + , + ; + current-limit = <10>; + }; + }; }; /* I2C1 in datasheet */ From 0d2b3e1f36b75eb188b8668bc63f0b218b7b2300 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 16 Feb 2024 11:05:49 +0100 Subject: [PATCH 012/981] samples: add IS31FL3194 RGB LED driver sample This sample app cycles several colors on an RGB LED forever using the LED API. It can be built and executed on an Arduino Nicla Sense ME, or on any board where the devicetree has a similar compatible I2C device node. Signed-off-by: Luca Burelli --- samples/drivers/led_is31fl3194/CMakeLists.txt | 7 +++ samples/drivers/led_is31fl3194/README.rst | 28 +++++++++ samples/drivers/led_is31fl3194/prj.conf | 2 + samples/drivers/led_is31fl3194/sample.yaml | 10 ++++ samples/drivers/led_is31fl3194/src/main.c | 58 +++++++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 samples/drivers/led_is31fl3194/CMakeLists.txt create mode 100644 samples/drivers/led_is31fl3194/README.rst create mode 100644 samples/drivers/led_is31fl3194/prj.conf create mode 100644 samples/drivers/led_is31fl3194/sample.yaml create mode 100644 samples/drivers/led_is31fl3194/src/main.c diff --git a/samples/drivers/led_is31fl3194/CMakeLists.txt b/samples/drivers/led_is31fl3194/CMakeLists.txt new file mode 100644 index 00000000000000..ed52c77a3fd0e4 --- /dev/null +++ b/samples/drivers/led_is31fl3194/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(led_is31fl3194) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/led_is31fl3194/README.rst b/samples/drivers/led_is31fl3194/README.rst new file mode 100644 index 00000000000000..0773587a4f80e0 --- /dev/null +++ b/samples/drivers/led_is31fl3194/README.rst @@ -0,0 +1,28 @@ +.. zephyr:code-sample:: is31fl3194 + :name: IS31FL3194 RGB LED + :relevant-api: led_interface + + Cycle colors on an RGB LED connected to the IS31FL3194 using the LED API. + +Overview +******** + +This sample cycles several colors on an RGB LED forever using the LED API. + +Building and Running +******************** + +This sample can be built and executed on an Arduino Nicla Sense ME, or on +any board where the devicetree has an I2C device node with compatible +:dtcompatible:`issi,is31fl3194` enabled, along with the relevant bus +controller node also being enabled. + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/led/issi_is31fl3194 + :board: arduino_nicla_sense_me + :goals: build flash + :compact: + +After flashing, the LED starts to switch colors and messages with the current +LED color are printed on the console. If a runtime error occurs, the sample +exits without printing to the console. diff --git a/samples/drivers/led_is31fl3194/prj.conf b/samples/drivers/led_is31fl3194/prj.conf new file mode 100644 index 00000000000000..555740ded902d5 --- /dev/null +++ b/samples/drivers/led_is31fl3194/prj.conf @@ -0,0 +1,2 @@ +CONFIG_LED=y +CONFIG_LOG=y diff --git a/samples/drivers/led_is31fl3194/sample.yaml b/samples/drivers/led_is31fl3194/sample.yaml new file mode 100644 index 00000000000000..0cb932b05d2ee7 --- /dev/null +++ b/samples/drivers/led_is31fl3194/sample.yaml @@ -0,0 +1,10 @@ +sample: + description: Demonstration of the IS31FL3194 LED driver + name: is31fl3194 sample +tests: + sample.drivers.led.is31fl3194: + filter: dt_compat_enabled("issi,is31fl3194") + tags: LED + depends_on: i2c + integration_platforms: + - arduino_nicla_sense_me diff --git a/samples/drivers/led_is31fl3194/src/main.c b/samples/drivers/led_is31fl3194/src/main.c new file mode 100644 index 00000000000000..335d152101b0f2 --- /dev/null +++ b/samples/drivers/led_is31fl3194/src/main.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* 1000 msec = 1 sec */ +#define SLEEP_TIME_MS 1000 + +/* Structure describing a color by its component values and name */ +struct color_data { + uint8_t r, g, b; + const char *name; +}; + +/* The sequence of colors the RGB LED will display */ +static const struct color_data color_sequence[] = { + { 0xFF, 0x00, 0x00, "Red" }, + { 0x00, 0xFF, 0x00, "Green" }, + { 0x00, 0x00, 0xFF, "Blue" }, + { 0xFF, 0xFF, 0xFF, "White" }, + { 0xFF, 0xFF, 0x00, "Yellow" }, + { 0xFF, 0x00, 0xFF, "Purple" }, + { 0x00, 0xFF, 0xFF, "Cyan" }, + { 0xF4, 0x79, 0x20, "Orange" }, +}; + +/* + * A build error on this line means your board is unsupported. + */ +const struct device *led = DEVICE_DT_GET_ANY(issi_is31fl3194); + +int main(void) +{ + int ret; + int i = 0; + + if (!device_is_ready(led)) { + return 0; + } + + while (1) { + ret = led_set_color(led, 0, 3, &(color_sequence[i].r)); + if (ret < 0) { + return 0; + } + + printk("LED color: %s\n", color_sequence[i].name); + k_msleep(SLEEP_TIME_MS); + i = (i + 1) % ARRAY_SIZE(color_sequence); + } + + return 0; +} From 1541fe9e2f787ac3a10d3d90297f185bbfa36a86 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 30 May 2024 15:01:27 +0300 Subject: [PATCH 013/981] intel_adsp/ace: power: fix address space annotation for powerdown power_down() expects a cached pointer. Fix the sparse annotation to match the implementation (sys_cache_cached_ptr_get() returns a cached pointer so this is correct). Signed-off-by: Kai Vehmanen --- soc/intel/intel_adsp/ace/power.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soc/intel/intel_adsp/ace/power.c b/soc/intel/intel_adsp/ace/power.c index afc270f9afa07f..6eb504178e3355 100644 --- a/soc/intel/intel_adsp/ace/power.c +++ b/soc/intel/intel_adsp/ace/power.c @@ -72,8 +72,8 @@ __imr void power_init(void) * (each bit corresponds to one ebb) * @param response_to_ipc flag if ipc response should be send during power down */ -extern void power_down(bool disable_lpsram, uint32_t *hpsram_pg_mask, - bool response_to_ipc); +extern void power_down(bool disable_lpsram, uint32_t __sparse_cache * hpsram_pg_mask, + bool response_to_ipc); #ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE /** From e087d1bbb364466ebf2a2c03fc74f7c9579e404d Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 30 May 2024 19:48:23 +0000 Subject: [PATCH 014/981] tests: drivers: can: api: add test for frame without data Add test for sending/receing a CAN classic frame with no data. Signed-off-by: Henrik Brix Andersen --- tests/drivers/can/api/src/classic.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/drivers/can/api/src/classic.c b/tests/drivers/can/api/src/classic.c index 9355651b7f19b4..077f547cad1023 100644 --- a/tests/drivers/can/api/src/classic.c +++ b/tests/drivers/can/api/src/classic.c @@ -818,6 +818,33 @@ ZTEST(can_classic, test_send_receive_std_id) &test_std_frame_1, &test_std_frame_2); } +/** + * @brief Test send/receive with standard (11-bit) CAN IDs without no data. + */ +ZTEST(can_classic, test_send_receive_std_id_no_data) +{ + const struct can_frame frame = { + .flags = 0, + .id = TEST_CAN_STD_ID_1, + .dlc = 0, + .data = { 0 } + }; + struct can_frame frame_buffer; + int filter_id; + int err; + + filter_id = add_rx_msgq(can_dev, &test_std_filter_1); + err = can_send(can_dev, &frame, TEST_SEND_TIMEOUT, NULL, NULL); + zassert_equal(err, 0, "failed to send frame without data (err %d)", err); + + err = k_msgq_get(&can_msgq, &frame_buffer, TEST_RECEIVE_TIMEOUT); + zassert_equal(err, 0, "receive timeout"); + + assert_frame_equal(&frame, &frame_buffer, 0); + + can_remove_rx_filter(can_dev, filter_id); +} + /** * @brief Test send/receive with extended (29-bit) CAN IDs. */ From 90c1aaad690bb3e206523972c9b11ddf64056b43 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Wed, 29 May 2024 10:20:43 -0500 Subject: [PATCH 015/981] tests: i2c_ram: Add fixture for i2c_ram testing i2c_ram expects that a ram-like part is connected to an i2c bus and therefore requires a hardware fixture setup much like spi_loopback. Adds a fixture that must be designated when running twister tests on a board with -X i2c_ram. Signed-off-by: Tom Burdick --- tests/drivers/i2c/i2c_ram/testcase.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/drivers/i2c/i2c_ram/testcase.yaml b/tests/drivers/i2c/i2c_ram/testcase.yaml index d1257778cc3fda..75bfbf0eb9a8bb 100644 --- a/tests/drivers/i2c/i2c_ram/testcase.yaml +++ b/tests/drivers/i2c/i2c_ram/testcase.yaml @@ -4,6 +4,9 @@ common: - drivers - i2c filter: dt_alias_exists("i2c-ram") + harness: ztest + harness_config: + fixture: i2c_ram tests: drivers.i2c.ram: depends_on: i2c From a9565f7a96b38a64631581a3ec54a3a9e8219c29 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Fri, 24 May 2024 11:38:10 +0200 Subject: [PATCH 016/981] docs: Add pytest files to a scope triggering doc-build workflow Those files are used with autoclass to use their docstrings in docs. Signed-off-by: Maciej Perkowski --- .github/workflows/doc-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index e8d53405257e93..e55b4bea247bc5 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -50,6 +50,8 @@ jobs: scripts/dts/ doc/requirements.txt .github/workflows/doc-build.yml + scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py + scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py doc-build-html: name: "Documentation Build (HTML)" From 209a3bd40aba88674eedbf2b9f16fc52720118fb Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Tue, 7 May 2024 13:46:20 +0200 Subject: [PATCH 017/981] coding guidelines: comply with MISRA Rule 11.8 - modified parameter types to receive a const pointer when a non-const pointer is not needed Signed-off-by: Hess Nathan --- tests/kernel/device/src/mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/kernel/device/src/mmio.c b/tests/kernel/device/src/mmio.c index a97060654bfec5..b8066eeea3ecf5 100644 --- a/tests/kernel/device/src/mmio.c +++ b/tests/kernel/device/src/mmio.c @@ -60,7 +60,7 @@ DEVICE_DEFINE(foo0, "foo0", foo_single_init, NULL, */ ZTEST(device, test_mmio_single) { - struct z_device_mmio_rom *rom; + const struct z_device_mmio_rom *rom; const struct device *dev = device_get_binding("foo0"); mm_reg_t regs; From aaec285cd59832da245a4b2fe33d6890aef0dbf7 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Thu, 2 May 2024 12:55:30 +0200 Subject: [PATCH 018/981] coding guidelines: comply with MISRA Rule 12.1. -added parentheses verifying lack of ambiguities Signed-off-by: Hess Nathan --- subsys/logging/log_minimal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/logging/log_minimal.c b/subsys/logging/log_minimal.c index 11a27f701bb473..1340cf59c27017 100644 --- a/subsys/logging/log_minimal.c +++ b/subsys/logging/log_minimal.c @@ -43,7 +43,7 @@ static void minimal_hexdump_line_print(const char *data, size_t length) if (i < length) { unsigned char c = data[i]; - printk("%c", isprint((int)c) != 0 ? c : '.'); + printk("%c", (isprint((int)c) != 0) ? c : '.'); } else { printk(" "); } From 3f90957e361f5153adc9a184a4c9277be23a03cd Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Thu, 23 May 2024 19:15:33 -0400 Subject: [PATCH 019/981] snippets: cdc-acm-console: Redirect Shell target to USB To easily enable Shell over USB. Tested with: ``` west build -b nrf52840dk/nrf52840 \ -S cdc-acm-console` \ samples/subsys/shell/shell_module ``` Signed-off-by: Luis Ubieda --- snippets/cdc-acm-console/cdc-acm-console.overlay | 1 + 1 file changed, 1 insertion(+) diff --git a/snippets/cdc-acm-console/cdc-acm-console.overlay b/snippets/cdc-acm-console/cdc-acm-console.overlay index 91e61886e522fa..52d8627803ce6d 100644 --- a/snippets/cdc-acm-console/cdc-acm-console.overlay +++ b/snippets/cdc-acm-console/cdc-acm-console.overlay @@ -7,6 +7,7 @@ / { chosen { zephyr,console = &snippet_cdc_acm_console_uart; + zephyr,shell-uart = &snippet_cdc_acm_console_uart; }; }; From 73bf6f6371f8fdc3061b7077d3ca130b77d155f0 Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Tue, 24 Oct 2023 14:42:32 +0200 Subject: [PATCH 020/981] samples: bluetooth: Enable PM on rd_rw612_bga Enable PM by default for rd_rw612_bga on peripheral_ht and central_ht samples Those are the BLE samples running on the CI, so it will be better to also check the builds with PM and also have some BLE apps to try PM with. Signed-off-by: Yassine El Aissaoui --- samples/bluetooth/central_ht/boards/rd_rw612_bga.conf | 1 + samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf | 1 + 2 files changed, 2 insertions(+) create mode 100644 samples/bluetooth/central_ht/boards/rd_rw612_bga.conf create mode 100644 samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf diff --git a/samples/bluetooth/central_ht/boards/rd_rw612_bga.conf b/samples/bluetooth/central_ht/boards/rd_rw612_bga.conf new file mode 100644 index 00000000000000..2df782efc71152 --- /dev/null +++ b/samples/bluetooth/central_ht/boards/rd_rw612_bga.conf @@ -0,0 +1 @@ +CONFIG_PM=y diff --git a/samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf b/samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf new file mode 100644 index 00000000000000..2df782efc71152 --- /dev/null +++ b/samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf @@ -0,0 +1 @@ +CONFIG_PM=y From 4fc6506a8af33e8025e9119fdddc96e007acb3ca Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 3 Jun 2024 17:46:52 +0200 Subject: [PATCH 021/981] random: enable AES support CTR_DRBG CSPRNG when it relies on Mbed TLS PR #72475 disabled default enabling of many Mbed TLS features including AES. This means that now it must be explicitly added when required. Signed-off-by: Valerio Setti --- subsys/random/Kconfig | 1 + tests/crypto/mbedtls/prj.conf | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/random/Kconfig b/subsys/random/Kconfig index 72106f09b57075..0124bb28b10211 100644 --- a/subsys/random/Kconfig +++ b/subsys/random/Kconfig @@ -107,6 +107,7 @@ config CTR_DRBG_CSPRNG_GENERATOR bool "Use CTR-DRBG CSPRNG" depends on MBEDTLS || TINYCRYPT depends on ENTROPY_HAS_DRIVER + select MBEDTLS_CIPHER_AES_ENABLED if MBEDTLS select TINYCRYPT_CTR_PRNG if TINYCRYPT select TINYCRYPT_AES if TINYCRYPT help diff --git a/tests/crypto/mbedtls/prj.conf b/tests/crypto/mbedtls/prj.conf index 7f9ee7aa45924b..6da7c1489b7cf9 100644 --- a/tests/crypto/mbedtls/prj.conf +++ b/tests/crypto/mbedtls/prj.conf @@ -9,6 +9,5 @@ CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y CONFIG_MINIMAL_LIBC_RAND=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y CONFIG_MBEDTLS_USE_PSA_CRYPTO=n CONFIG_PSA_CRYPTO_ENABLE_ALL=n From 059643062c2109ffa56f9a0da578a0f02f24f940 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Mon, 3 Jun 2024 14:12:28 +0200 Subject: [PATCH 022/981] usb: device_next: Update remote wakeup log level The `Remote wakeup feature not enabled or not suspended` log is not related to an actual error (connected host might not enable USB remote wakeup feature). Use warning log level. Signed-off-by: Marek Pieta --- subsys/usb/device_next/usbd_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/usb/device_next/usbd_device.c b/subsys/usb/device_next/usbd_device.c index 86570a12675855..b2ba1fe3cffc24 100644 --- a/subsys/usb/device_next/usbd_device.c +++ b/subsys/usb/device_next/usbd_device.c @@ -160,7 +160,7 @@ int usbd_wakeup_request(struct usbd_context *const uds_ctx) } if (!uds_ctx->status.rwup || !usbd_is_suspended(uds_ctx)) { - LOG_ERR("Remote wakeup feature not enabled or not suspended"); + LOG_WRN("Remote wakeup feature not enabled or not suspended"); ret = -EACCES; goto wakeup_request_error; } From f33306ab2f41710e5b260c3b4ea4a031585c066b Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Fri, 31 May 2024 00:56:19 +0100 Subject: [PATCH 023/981] MAINTAINERS: add hostlink channel sources to Synopsys Platforms Virtual UART over ARC hostlink channel driver is used on Synopsys platforms and maintained by Synopsys. Signed-off-by: Evgeniy Paltsev Signed-off-by: Eugeniy Paltsev --- MAINTAINERS.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index c0122d065defa9..b6346106bb426d 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3172,6 +3172,8 @@ Synopsys Platforms: - scripts/west_commands/tests/test_mdb.py - scripts/west_commands/runners/nsim.py - cmake/emu/nsim.cmake + - drivers/serial/uart_hostlink.c + - drivers/serial/Kconfig.hostlink labels: - "platform: Synopsys" From c93859c6596ad6e927d3a9823fb4f08c156c90fc Mon Sep 17 00:00:00 2001 From: alperen sener Date: Thu, 30 May 2024 12:52:56 +0200 Subject: [PATCH 024/981] bluetooth: mesh: fix lpn receive window timing error APIs for enabling and disabling the scanner may take larger time than expected and scheduling of the lpn state machine is affected by it. Since these type of latencies are factored into timeouts and scheduling times, we need to call scan enable/disable APIs after scheduling the next event time for LPN state machine to be more accurate. Signed-off-by: alperen sener --- subsys/bluetooth/mesh/lpn.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/mesh/lpn.c b/subsys/bluetooth/mesh/lpn.c index 0d14c9c55e5698..a7e48e841d1a83 100644 --- a/subsys/bluetooth/mesh/lpn.c +++ b/subsys/bluetooth/mesh/lpn.c @@ -296,11 +296,11 @@ static void clear_friendship(bool force, bool disable) if (!disable) { lpn_set_state(BT_MESH_LPN_ENABLED); + k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); + if (!IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { bt_mesh_scan_enable(); } - - k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); } if (was_established) { @@ -570,7 +570,6 @@ static void friend_response_received(struct bt_mesh_lpn *lpn) lpn->fsn++; } - bt_mesh_scan_disable(); lpn_set_state(BT_MESH_LPN_ESTABLISHED); lpn->req_attempts = 0U; lpn->sent_req = 0U; @@ -581,6 +580,7 @@ static void friend_response_received(struct bt_mesh_lpn *lpn) int32_t timeout = poll_timeout(lpn); k_work_reschedule(&lpn->timer, K_MSEC(timeout)); + bt_mesh_scan_disable(); } void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) @@ -857,9 +857,9 @@ static void update_timeout(struct bt_mesh_lpn *lpn) { if (lpn->established) { LOG_WRN("No response from Friend during ReceiveWindow"); - bt_mesh_scan_disable(); lpn_set_state(BT_MESH_LPN_ESTABLISHED); k_work_reschedule(&lpn->timer, K_MSEC(POLL_RETRY_TIMEOUT)); + bt_mesh_scan_disable(); } else { if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { bt_mesh_scan_disable(); @@ -903,19 +903,19 @@ static void lpn_timeout(struct k_work *work) send_friend_req(lpn); break; case BT_MESH_LPN_REQ_WAIT: - bt_mesh_scan_enable(); k_work_reschedule(&lpn->timer, K_MSEC(lpn->adv_duration + FRIEND_REQ_SCAN)); lpn_set_state(BT_MESH_LPN_WAIT_OFFER); + bt_mesh_scan_enable(); break; case BT_MESH_LPN_WAIT_OFFER: LOG_WRN("No acceptable Friend Offers received"); - if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - bt_mesh_scan_disable(); - } - lpn_set_state(BT_MESH_LPN_ENABLED); lpn->sent_req = 0U; k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); + + if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { + bt_mesh_scan_disable(); + } break; case BT_MESH_LPN_ESTABLISHED: if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { @@ -939,8 +939,8 @@ static void lpn_timeout(struct k_work *work) case BT_MESH_LPN_RECV_DELAY: k_work_reschedule(&lpn->timer, K_MSEC(SCAN_LATENCY + lpn->recv_win + RX_DELAY_CORRECTION(lpn))); - bt_mesh_scan_enable(); lpn_set_state(BT_MESH_LPN_WAIT_UPDATE); + bt_mesh_scan_enable(); break; case BT_MESH_LPN_WAIT_UPDATE: update_timeout(lpn); From a33341ac6676c527d9ba14d23b815157d492c7d5 Mon Sep 17 00:00:00 2001 From: Tom Chang Date: Thu, 30 May 2024 13:45:47 +0800 Subject: [PATCH 025/981] drivers: espi: npcx: add support 66MHz eSPI clock This CL adds support 66MHz eSPI clock for NPCX4. Signed-off-by: Tom Chang --- drivers/espi/espi_npcx.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index 05d7b60e2eafd0..de23de2b46a145 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -69,6 +69,7 @@ struct espi_npcx_data { #define NPCX_ESPI_MAXFREQ_25 1 #define NPCX_ESPI_MAXFREQ_33 2 #define NPCX_ESPI_MAXFREQ_50 3 +#define NPCX_ESPI_MAXFREQ_66 4 /* Minimum delay before acknowledging a virtual wire */ #define NPCX_ESPI_VWIRE_ACK_DELAY 10ul /* 10 us */ @@ -676,6 +677,11 @@ static int espi_npcx_configure(const struct device *dev, struct espi_cfg *cfg) case 50: max_freq = NPCX_ESPI_MAXFREQ_50; break; +#ifdef CONFIG_SOC_SERIES_NPCX4 + case 66: + max_freq = NPCX_ESPI_MAXFREQ_66; + break; +#endif default: return -EINVAL; } From af63e488f01b92a9ba124f90ec08bb7d2672aa73 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Wed, 29 May 2024 14:57:52 +0200 Subject: [PATCH 026/981] usb: device_next: hid: fix Get Report buffer handling After the get_report() callback, we need to determine how many bytes the HID device wrote to the report buffer. Use the callback return value to do this, and modify the net_buf data length value if get_report was successful. Reported-by: Marek Pieta Signed-off-by: Johann Fischer --- include/zephyr/usb/class/usbd_hid.h | 6 ++++-- subsys/usb/device_next/class/usbd_hid.c | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/zephyr/usb/class/usbd_hid.h b/include/zephyr/usb/class/usbd_hid.h index 5dd6d0dad2354f..9798b081093dad 100644 --- a/include/zephyr/usb/class/usbd_hid.h +++ b/include/zephyr/usb/class/usbd_hid.h @@ -106,8 +106,10 @@ struct hid_device_ops { * feature, input, or output report, which is specified by the argument * type. If there is no report ID in the report descriptor, the id * argument is zero. The callback implementation must check the - * arguments, such as whether the report type is supported, and return - * a nonzero value to indicate an unsupported type or an error. + * arguments, such as whether the report type is supported and the + * report length, and return a negative value to indicate an + * unsupported type or an error, or return the length of the report + * written to the buffer. */ int (*get_report)(const struct device *dev, const uint8_t type, const uint8_t id, diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c index 6fef55df27f39b..1b39aa182cf942 100644 --- a/subsys/usb/device_next/class/usbd_hid.c +++ b/subsys/usb/device_next/class/usbd_hid.c @@ -231,25 +231,34 @@ static int handle_get_report(const struct device *dev, const uint8_t id = HID_GET_REPORT_ID(setup->wValue); struct hid_device_data *const ddata = dev->data; const struct hid_device_ops *ops = ddata->ops; + const size_t size = net_buf_tailroom(buf); + int ret = 0; switch (type) { case HID_REPORT_TYPE_INPUT: LOG_DBG("Get Report, Input Report ID %u", id); - errno = ops->get_report(dev, type, id, net_buf_tailroom(buf), buf->data); + ret = ops->get_report(dev, type, id, size, buf->data); break; case HID_REPORT_TYPE_OUTPUT: LOG_DBG("Get Report, Output Report ID %u", id); - errno = ops->get_report(dev, type, id, net_buf_tailroom(buf), buf->data); + ret = ops->get_report(dev, type, id, size, buf->data); break; case HID_REPORT_TYPE_FEATURE: LOG_DBG("Get Report, Feature Report ID %u", id); - errno = ops->get_report(dev, type, id, net_buf_tailroom(buf), buf->data); + ret = ops->get_report(dev, type, id, size, buf->data); break; default: errno = -ENOTSUP; break; } + if (ret > 0) { + __ASSERT(ret <= size, "Buffer overflow in the HID driver"); + net_buf_add(buf, MIN(size, ret)); + } else { + errno = ret ? ret : -ENOTSUP; + } + return 0; } From 7f0b5edd8c23ce1b285d00f7f376e5ad5a23c6ef Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Tue, 28 May 2024 21:23:28 -0700 Subject: [PATCH 027/981] arch/x86: Make irq_offload SMP-safe on x86_64 The irq_offload mechanism was using the same entry of the IDT vector for all CPUs on SMP systems. This caused race conditions when two CPUs were doing irq_offload() calls. This patch addresses that by adding one indirection layer: the irq_offload() now sets a per CPU entry with the routine and parameter to be run. Then a software interrupt is generated, and a default handler will do the appropriate dispatching. Finally, test "kernel/smp_abort" is enabled for x86 as it should work now. Fixes #72172. Signed-off-by: Ederson de Souza --- arch/x86/core/intel64/irq_offload.c | 32 +++++++++++++++++++++++++--- tests/kernel/smp_abort/testcase.yaml | 1 - 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/arch/x86/core/intel64/irq_offload.c b/arch/x86/core/intel64/irq_offload.c index 0146321f7d9d99..c2771d735cfc25 100644 --- a/arch/x86/core/intel64/irq_offload.c +++ b/arch/x86/core/intel64/irq_offload.c @@ -9,6 +9,7 @@ */ #include +#include #include #include @@ -17,12 +18,37 @@ extern void (*x86_irq_funcs[NR_IRQ_VECTORS])(const void *arg); extern const void *x86_irq_args[NR_IRQ_VECTORS]; +static void (*irq_offload_funcs[CONFIG_MP_NUM_CPUS])(const void *arg); +static const void *irq_offload_args[CONFIG_MP_NUM_CPUS]; + +static void dispatcher(const void *arg) +{ + uint8_t cpu_id = _current_cpu->id; + + if (irq_offload_funcs[cpu_id] != NULL) { + irq_offload_funcs[cpu_id](irq_offload_args[cpu_id]); + } +} 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; + int key = arch_irq_lock(); + uint8_t cpu_id = _current_cpu->id; + + irq_offload_funcs[cpu_id] = routine; + irq_offload_args[cpu_id] = parameter; + __asm__ volatile("int %0" : : "i" (CONFIG_IRQ_OFFLOAD_VECTOR) : "memory"); - x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = NULL; + + arch_irq_unlock(key); +} + +int irq_offload_init(void) +{ + x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = dispatcher; + + return 0; } + +SYS_INIT(irq_offload_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/tests/kernel/smp_abort/testcase.yaml b/tests/kernel/smp_abort/testcase.yaml index 3903e477e178c8..3b5a006991a46b 100644 --- a/tests/kernel/smp_abort/testcase.yaml +++ b/tests/kernel/smp_abort/testcase.yaml @@ -1,6 +1,5 @@ tests: kernel.smp_abort: - arch_exclude: x86 # Buggy irq_offload(), see #71172 tags: - kernel - smp From d877d299137ce8d325468ef563f13c823f626a7d Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Wed, 22 May 2024 14:55:49 -0400 Subject: [PATCH 028/981] twister: abort on execution and retun 0 on exceptions When something goes wrong with execution, due to twister issues and bugs, do not continue with execution and abort the process and report and return an error code. Fixes #72807 Signed-off-by: Anas Nashif --- scripts/pylib/twister/twisterlib/runner.py | 39 +++++++++++++--------- scripts/tests/twister/test_runner.py | 1 + 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 7251f3f733ceba..6725134cc24ebb 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -1315,8 +1315,22 @@ def add_tasks_to_queue(self, pipeline, build_only=False, test_only=False, retry_ def pipeline_mgr(self, pipeline, done_queue, lock, results): - if sys.platform == 'linux': - with self.jobserver.get_job(): + try: + if sys.platform == 'linux': + with self.jobserver.get_job(): + while True: + try: + task = pipeline.get_nowait() + except queue.Empty: + break + else: + instance = task['test'] + pb = ProjectBuilder(instance, self.env, self.jobserver) + pb.duts = self.duts + pb.process(pipeline, done_queue, task, lock, results) + + return True + else: while True: try: task = pipeline.get_nowait() @@ -1327,20 +1341,10 @@ def pipeline_mgr(self, pipeline, done_queue, lock, results): pb = ProjectBuilder(instance, self.env, self.jobserver) pb.duts = self.duts pb.process(pipeline, done_queue, task, lock, results) - return True - else: - while True: - try: - task = pipeline.get_nowait() - except queue.Empty: - break - else: - instance = task['test'] - pb = ProjectBuilder(instance, self.env, self.jobserver) - pb.duts = self.duts - pb.process(pipeline, done_queue, task, lock, results) - return True + except Exception as e: + logger.error(f"General exception: {e}") + sys.exit(1) def execute(self, pipeline, done): lock = Lock() @@ -1360,6 +1364,11 @@ def execute(self, pipeline, done): try: for p in processes: p.join() + if p.exitcode != 0: + logger.error(f"Process {p.pid} failed, aborting execution") + for proc in processes: + proc.terminate() + sys.exit(1) except KeyboardInterrupt: logger.info("Execution interrupted") for p in processes: diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index 592d2c63042086..88ed43a87fef8b 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -2691,6 +2691,7 @@ def mock_join(): process_mock = mock.Mock() process_mock().join = mock.Mock(side_effect=mock_join) + process_mock().exitcode = 0 pipeline_mock = mock.Mock() done_mock = mock.Mock() From d05cad1784be697640223b53e4d16b5848b320e3 Mon Sep 17 00:00:00 2001 From: Krystof Sadlik Date: Wed, 29 May 2024 16:14:14 +0200 Subject: [PATCH 029/981] tests: i2c: i2c_target_api: added single mode testcase Some drivers do not support dual mode testcase. It would be great to test both signle and dual mode, even when the drivers do support this feature. Signed-off-by: Krystof Sadlik --- .../i2c/i2c_target_api/boards/mimxrt1040_evk.overlay | 10 ++-------- .../boards/mimxrt1170_evk_mimxrt1176_cm7.conf | 1 + ...B.overlay => mimxrt1170_evk_mimxrt1176_cm7.overlay} | 0 .../boards/mimxrt1170_evkb_mimxrt1176_cm4.conf | 1 + ....overlay => mimxrt1170_evkb_mimxrt1176_cm4.overlay} | 0 .../boards/mimxrt1170_evkb_mimxrt1176_cm7.conf | 1 + ....overlay => mimxrt1170_evkb_mimxrt1176_cm7.overlay} | 0 tests/drivers/i2c/i2c_target_api/testcase.yaml | 7 +++++++ 8 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.conf rename tests/drivers/i2c/i2c_target_api/boards/{mimxrt1170_evk_mimxrt1176_cm4_B.overlay => mimxrt1170_evk_mimxrt1176_cm7.overlay} (100%) create mode 100644 tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.conf rename tests/drivers/i2c/i2c_target_api/boards/{mimxrt1170_evk_mimxrt1176_cm7_B.overlay => mimxrt1170_evkb_mimxrt1176_cm4.overlay} (100%) create mode 100644 tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.conf rename tests/drivers/i2c/i2c_target_api/boards/{mimxrt1170_evkb_cm4.overlay => mimxrt1170_evkb_mimxrt1176_cm7.overlay} (100%) diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay index 5dbcf85abb6557..ba70b01c1d424b 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay @@ -15,23 +15,17 @@ &lpi2c1 { status = "okay"; eeprom0: eeprom@54 { - compatible = "atmel,at24"; + compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; size = <1024>; - pagesize = <16>; - address-width = <8>; - timeout = <5>; }; }; &lpi2c3 { status = "okay"; eeprom1: eeprom@56 { - compatible = "atmel,at24"; + compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; size = <1024>; - pagesize = <16>; - address-width = <8>; - timeout = <5>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.conf b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.conf new file mode 100644 index 00000000000000..70e009fae68aea --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.conf @@ -0,0 +1 @@ +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm4_B.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay similarity index 100% rename from tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm4_B.overlay rename to tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.conf b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.conf new file mode 100644 index 00000000000000..70e009fae68aea --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.conf @@ -0,0 +1 @@ +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay similarity index 100% rename from tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay rename to tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.conf b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.conf new file mode 100644 index 00000000000000..70e009fae68aea --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.conf @@ -0,0 +1 @@ +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_cm4.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay similarity index 100% rename from tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_cm4.overlay rename to tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay diff --git a/tests/drivers/i2c/i2c_target_api/testcase.yaml b/tests/drivers/i2c/i2c_target_api/testcase.yaml index f3883c0459ce6e..ca8f3a59bbfd2b 100644 --- a/tests/drivers/i2c/i2c_target_api/testcase.yaml +++ b/tests/drivers/i2c/i2c_target_api/testcase.yaml @@ -32,3 +32,10 @@ tests: - nucleo_f091rc extra_configs: - CONFIG_APP_DUAL_ROLE_I2C=y + drivers.i2c.target_api.single_role: + platform_allow: + - frdm_mcxn947/mcxn947/cpu0 + - mimxrt1170_evk@B/mimxrt1176/cm7 + - mimxrt1170_evk/mimxrt1176/cm7 + - mimxrt1040_evk + - mimxrt1060_evk From fe60a49c6755832c6d435f4915f8d6cfe3c18bab Mon Sep 17 00:00:00 2001 From: Krystof Sadlik Date: Mon, 3 Jun 2024 16:34:25 +0200 Subject: [PATCH 030/981] tests: i2c: i2c_target_api: fixed sizes in ovelay Fixed sizes in ovelay files. Signed-off-by: Krystof Sadlik --- .../drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay | 4 ++-- .../drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay | 4 ++-- .../boards/mimxrt1170_evk_mimxrt1176_cm7.overlay | 4 ++-- .../boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay | 4 ++-- .../boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay index ba70b01c1d424b..a1c329a6926e69 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay @@ -17,7 +17,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -26,6 +26,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay index 143c437549f0b8..d47c67068ba92e 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay @@ -25,7 +25,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -36,6 +36,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay index 4e17adc5dce5b8..967f9a7de3858e 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay @@ -11,7 +11,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -20,6 +20,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay index 4e17adc5dce5b8..967f9a7de3858e 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay @@ -11,7 +11,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -20,6 +20,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay index 4e17adc5dce5b8..967f9a7de3858e 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay @@ -11,7 +11,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -20,6 +20,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; From fb61c7b360a7471d4fe2e95ab9b2a507296f8935 Mon Sep 17 00:00:00 2001 From: Krystof Sadlik Date: Mon, 3 Jun 2024 17:56:07 +0200 Subject: [PATCH 031/981] tests: i2c: Fixed overlay for frdm board Fixed overlay for frdm board as well. Signed-off-by: Krystof Sadlik --- .../i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/drivers/i2c/i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay b/tests/drivers/i2c/i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay index d0dc5661db8c3d..71a99565aab4e4 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay @@ -38,7 +38,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -46,6 +46,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; From b3c9f957c6e5fe5aea7b4b9796ff9d38b23839c4 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Sep 2023 18:48:37 +0000 Subject: [PATCH 032/981] drivers/flash: Add explicit_erase property The commit adds and no_explicit_erase capability to flash_parameters, that indicates whether device is program-erase type device; such devices, like Flash type devices, require erase prior to writing random data at any previously programmed location. This capability should only be set by drivers. The flash_params_get_erase_cap() function has been added, for parsing flash_parameters object to obtain erase capabilities of device. The function returns capabilities as combination of bits representing them. Currently it will return: 0 -- no erase capabilities FLASH_ERASE_C_EXPLICIT -- erase required before write of random data. Additional capabilities have been reserved but are not yet used. There are following Kconfig options added: FLASH_HAS_EXPLICIT_ERASE FLASH_HAS_NO_EXPLICIT_ERASE that should be selected by device driver to indicate whether devices served by driver needs erase prior to write. The above Kconfigs are used to figure out whether app is built for hardware that requires erase prior to write. They can be also used to detect that it is attempted to build some subsystem that will not work with provided hardware, for example file system that has not been prepared to work with devices that do not require erase. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig | 58 ++++++++++++++++++++++++++++++++-- include/zephyr/drivers/flash.h | 52 +++++++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 3 deletions(-) diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index 441a79868786f5..2762cd913f225b 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -17,6 +17,56 @@ config FLASH_HAS_EX_OP This option is selected by drivers that support flash extended operations. +config FLASH_HAS_EXPLICIT_ERASE + bool + help + Device has does not do erase-on-write (erase-on-program, auto-erase + on write) and requires explicit erase procedure to be programmed + with random value, in place where it has already been programmed with + some other value, as program can only change bits from erased-value + to the opposite. + All pure Flash devices are evolution of EEPROM where erase has + been separated from write, EEPROM has erase-on-write, giving + it advantage of higher write speeds at a cost of larger erase block. + Note that explicit-erase capability does not warrants that + write without erase is not allowed, taking the above restrictions, + it only states that write of a random information will require + erase. + Erase is usually performed in pages, as we have chosen to name + the unit in Zephyr, that may have different naming in device + specifications, like pages, sectors or blocks, and may vary + in size, depending how they are named by vendor. + This option should be selected by drivers that serve devices with + such characteristic and is used and may be used by users to provide + paths in code that only serve such devices, and could be + optimized-out by compiler in case where there is no such device in + a system. + +config FLASH_HAS_NO_EXPLICIT_ERASE + bool + help + Device does not require explicit erase before programming + a new random value at any location that has been previously + programmed with some other value. + Note that the device may have erase-on-write (auto-erase), + as for example in EEPROM devices, but may also have no erase + at all. + A device driver may still provide erase callback, + especially if it is able to perform erase to accelerate + further writes or is able to fill the area requested for + erase, with single value, faster than consecutive writes + that would be used to emulate erase. + This option should be selected by drivers that serve + devices with such characteristic and is used and may be + used by users to provide paths in code that only serve + such devices, and could be optimized-out by compiler in + case where there is no such device in a system. + This option should be selected for any device that + can change storage bits, by write, from any value to opposite + value at any time. + When your driver sets this option you also need to set + no_explicit_erase capability in your drivers flash_parameters. + config FLASH_HAS_PAGE_LAYOUT bool help @@ -77,13 +127,17 @@ config FLASH_SHELL_BUFFER_SIZE endif # FLASH_SHELL + +if FLASH_HAS_PAGE_LAYOUT + config FLASH_PAGE_LAYOUT bool "API for retrieving the layout of pages" - depends on FLASH_HAS_PAGE_LAYOUT - default y + default FLASH_HAS_PAGE_LAYOUT help Enables API for retrieving the layout of flash memory pages. +endif + config FLASH_EX_OP_ENABLED bool "API for extended flash operations" depends on FLASH_HAS_EX_OP diff --git a/include/zephyr/drivers/flash.h b/include/zephyr/drivers/flash.h index beb8838d71e9e3..ecc0f4d0e29bcb 100644 --- a/include/zephyr/drivers/flash.h +++ b/include/zephyr/drivers/flash.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2017-2024 Nordic Semiconductor ASA * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 @@ -58,9 +58,59 @@ struct flash_pages_layout { */ struct flash_parameters { const size_t write_block_size; + /* Device capabilities. Only drivers are supposed to set the + * capabilities directly, users need to call the FLASH_CAPS_ + * macros on pointer to flash_parameters to get capabilities. + */ + struct { + /* Device has no explicit erase, so it either erases on + * write or does not require it at all. + * This also includes devices that support erase but + * do not require it. + */ + bool no_explicit_erase: 1; + } caps; uint8_t erase_value; /* Byte value of erased flash */ }; +/** Set for ordinary Flash where erase is needed before write of random data */ +#define FLASH_ERASE_C_EXPLICIT 0x01 +/** Reserved for users as initializer for variables that will later store + * capabilities. + */ +#define FLASH_ERASE_CAPS_UNSET (int)-1 +/* The values below are now reserved but not used */ +#define FLASH_ERASE_C_SUPPORTED 0x02 +#define FLASH_ERASE_C_VAL_BIT 0x04 +#define FLASH_ERASE_UNIFORM_PAGE 0x08 + + +/* @brief Parser for flash_parameters for retrieving erase capabilities + * + * The functions parses flash_parameters type object and returns combination + * of erase capabilities of 0 if device does not have any. + * Not that in some cases availability of erase may be dependent on driver + * options, so even if by hardware design a device provides some erase + * capabilities, the function may return 0 if these been disabled or not + * implemented by driver. + * + * @param p pointer to flash_parameters type object + * + * @return 0 or combination of FLASH_ERASE_C_ capabilities. + */ +static inline +int flash_params_get_erase_cap(const struct flash_parameters *p) +{ +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) +#if defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + return (p->caps.no_explicit_erase) ? 0 : FLASH_ERASE_C_EXPLICIT; +#else + return FLASH_ERASE_C_EXPLICIT; +#endif +#endif + return 0; +} + /** * @} */ From 010b8d19e935bfba11317ffde75c8cfc2fd338d0 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Sep 2023 18:53:55 +0000 Subject: [PATCH 033/981] tests/drivers/flash: Make tests check for explicit erase capability Test now check whether device has requirement for explicit erase before call or not, before performing various actions. Signed-off-by: Dominik Ermel --- tests/drivers/flash/common/src/main.c | 75 +++++++++++++++++++-------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/tests/drivers/flash/common/src/main.c b/tests/drivers/flash/common/src/main.c index d3c5d8b7cf6092..8b6bb80ecab8bd 100644 --- a/tests/drivers/flash/common/src/main.c +++ b/tests/drivers/flash/common/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2022 Nordic Semiconductor ASA + * Copyright (c) 2020-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,11 +44,16 @@ #define EXPECTED_SIZE 512 +#if !IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && \ + !IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) +#error There is no flash device enabled or it is missing Kconfig options +#endif + static const struct device *const flash_dev = TEST_AREA_DEVICE; static struct flash_pages_info page_info; static uint8_t __aligned(4) expected[EXPECTED_SIZE]; -static const struct flash_parameters *flash_params; static uint8_t erase_value; +static bool ebw_required; static void *flash_driver_setup(void) { @@ -57,12 +62,22 @@ static void *flash_driver_setup(void) TC_PRINT("Test will run on device %s\n", flash_dev->name); zassert_true(device_is_ready(flash_dev)); - flash_params = flash_get_parameters(flash_dev); - erase_value = flash_params->erase_value; + /* Check for erase is only needed when there is mix of devices */ + if (IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE)) { + const struct flash_parameters *fparams = flash_get_parameters(flash_dev); + + erase_value = fparams->erase_value; + ebw_required = flash_params_get_erase_cap(fparams) & FLASH_ERASE_C_EXPLICIT; + /* For tests purposes use page (in nrf_qspi_nor page = 64 kB) */ + flash_get_page_info_by_offs(flash_dev, TEST_AREA_OFFSET, + &page_info); + } else { + TC_PRINT("No devices with erase requirement present\n"); + erase_value = 0x55; + page_info.start_offset = TEST_AREA_OFFSET; + page_info.size = TEST_AREA_MAX - TEST_AREA_OFFSET; + } - /* For tests purposes use page (in nrf_qspi_nor page = 64 kB) */ - flash_get_page_info_by_offs(flash_dev, TEST_AREA_OFFSET, - &page_info); /* Check if test region is not empty */ uint8_t buf[EXPECTED_SIZE]; @@ -85,23 +100,25 @@ static void *flash_driver_setup(void) "Test area exceeds flash size"); /* Check if flash is cleared */ - bool is_buf_clear = true; + if (IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && ebw_required) { + bool is_buf_clear = true; - for (off_t i = 0; i < EXPECTED_SIZE; i++) { - if (buf[i] != erase_value) { - is_buf_clear = false; - break; + for (off_t i = 0; i < EXPECTED_SIZE; i++) { + if (buf[i] != erase_value) { + is_buf_clear = false; + break; + } } - } - if (!is_buf_clear) { - /* Erase a nb of pages aligned to the EXPECTED_SIZE */ - rc = flash_erase(flash_dev, page_info.start_offset, - (page_info.size * - ((EXPECTED_SIZE + page_info.size - 1) - / page_info.size))); + if (!is_buf_clear) { + /* Erase a nb of pages aligned to the EXPECTED_SIZE */ + rc = flash_erase(flash_dev, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); - zassert_equal(rc, 0, "Flash memory not properly erased"); + zassert_equal(rc, 0, "Flash memory not properly erased"); + } } return NULL; @@ -112,9 +129,23 @@ ZTEST(flash_driver, test_read_unaligned_address) int rc; uint8_t buf[EXPECTED_SIZE]; const uint8_t canary = erase_value; + uint32_t start; + + if (IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && ebw_required) { + start = page_info.start_offset; + /* Erase a nb of pages aligned to the EXPECTED_SIZE */ + rc = flash_erase(flash_dev, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + + zassert_equal(rc, 0, "Flash memory not properly erased"); + } else { + start = TEST_AREA_OFFSET; + } rc = flash_write(flash_dev, - page_info.start_offset, + start, expected, EXPECTED_SIZE); zassert_equal(rc, 0, "Cannot write to flash"); @@ -129,7 +160,7 @@ ZTEST(flash_driver, test_read_unaligned_address) buf[buf_o + len] = canary; memset(buf + buf_o, 0, len); rc = flash_read(flash_dev, - page_info.start_offset + ad_o, + start + ad_o, buf + buf_o, len); zassert_equal(rc, 0, "Cannot read flash"); zassert_equal(memcmp(buf + buf_o, From b8d073c572057354e3865f9aeafdad76eb6b3fb4 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 7 Mar 2024 22:42:41 +0000 Subject: [PATCH 034/981] drivers/flash: Add flash_fill() and flash_flatten() The commit adds two new API calls: - flash_fill - that allows to fill selected part of device with specified value; - flash_flatten - that allows to erase or fill device with erase_value, depending on whether driver for the device provides erase callback. Signed-off-by: Dominik Ermel --- drivers/flash/CMakeLists.txt | 2 + drivers/flash/Kconfig | 13 +++++ drivers/flash/flash_handlers.c | 16 ++++++ drivers/flash/flash_util.c | 82 +++++++++++++++++++++++++++ include/zephyr/drivers/flash.h | 60 +++++++++++++++++++- tests/drivers/flash/common/src/main.c | 74 ++++++++++++++++++++++++ 6 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 drivers/flash/flash_util.c diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index 54b9178c091831..744a6a5862c855 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_library_sources(flash_util.c) + zephyr_syscall_header_ifdef( CONFIG_FLASH_SIMULATOR ${ZEPHYR_BASE}/include/zephyr/drivers/flash/flash_simulator.h diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index 2762cd913f225b..4816db0b580f53 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -127,6 +127,19 @@ config FLASH_SHELL_BUFFER_SIZE endif # FLASH_SHELL +config FLASH_FILL_BUFFER_SIZE + int "Buffer size of flash_fill funciton" + default 32 + help + Size of a buffer used by flash_fill function to fill a device with + specific value; this buffer is allocated on stack. + The buffer is needed as most devices have write-block alignment + requirements that which imposes minimal size of data, which can + be written to a device, and alignment of write offset. + Even if device does not have such requirement, filling device by + single bytes is not efficient. + Value selected here should be multiply of the largest write-block-size + among all the memory devices used in system. if FLASH_HAS_PAGE_LAYOUT diff --git a/drivers/flash/flash_handlers.c b/drivers/flash/flash_handlers.c index 6e47b10dbd383d..338c6c8402d61e 100644 --- a/drivers/flash/flash_handlers.c +++ b/drivers/flash/flash_handlers.c @@ -50,6 +50,22 @@ static inline const struct flash_parameters *z_vrfy_flash_get_parameters(const s } #include +int z_vrfy_flash_fill(const struct device *dev, uint8_t val, off_t offset, + size_t size) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); + return z_impl_flash_fill(dev, val, offset, size); +} +#include + +int z_vrfy_flash_flatten(const struct device *dev, off_t offset, size_t size) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); + return z_impl_flash_flatten(dev, offset, size); +} + +#include + #ifdef CONFIG_FLASH_PAGE_LAYOUT static inline int z_vrfy_flash_get_page_info_by_offs(const struct device *dev, off_t offs, diff --git a/drivers/flash/flash_util.c b/drivers/flash/flash_util.c new file mode 100644 index 00000000000000..ee3b55798a56b3 --- /dev/null +++ b/drivers/flash/flash_util.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include + +#include +#include +#include + +LOG_MODULE_REGISTER(flash, CONFIG_FLASH_LOG_LEVEL); + +int z_impl_flash_fill(const struct device *dev, uint8_t val, off_t offset, + size_t size) +{ + uint8_t filler[CONFIG_FLASH_FILL_BUFFER_SIZE]; + const struct flash_driver_api *api = + (const struct flash_driver_api *)dev->api; + const struct flash_parameters *fparams = api->get_parameters(dev); + int rc = 0; + size_t stored = 0; + + if (sizeof(filler) < fparams->write_block_size) { + LOG_ERR("Size of CONFIG_FLASH_FILL_BUFFER_SIZE"); + return -EINVAL; + } + /* The flash_write will, probably, check write alignment but this + * is too late, as we write datain chunks; data alignment may be + * broken by the size of the last chunk, that is why the check + * happens here too. + * Note that we have no way to check whether offset and size are + * are correct, as such info is only available at the level of + * a driver, so only basic check on offset. + */ + if (offset < 0) { + LOG_ERR("Negative offset not allowed\n"); + return -EINVAL; + } + if ((size | (size_t)offset) & (fparams->write_block_size - 1)) { + LOG_ERR("Incorrect size or offset alignment, expected %zx\n", + fparams->write_block_size); + return -EINVAL; + } + + memset(filler, val, sizeof(filler)); + + while (stored < size) { + size_t chunk = MIN(sizeof(filler), size); + + rc = api->write(dev, offset + stored, filler, chunk); + if (rc < 0) { + LOG_DBG("Fill to dev %p failed at offset 0x%zx\n", + dev, (size_t)offset + stored); + break; + } + stored += chunk; + } + return rc; +} + +int z_impl_flash_flatten(const struct device *dev, off_t offset, size_t size) +{ + const struct flash_driver_api *api = + (const struct flash_driver_api *)dev->api; + const struct flash_parameters *params = api->get_parameters(dev); + +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) + if ((flash_params_get_erase_cap(params) & FLASH_ERASE_C_EXPLICIT) && + api->erase != NULL) { + return api->erase(dev, offset, size); + } +#endif + +#if IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + return flash_fill(dev, params->erase_value, offset, size); +#else + return -ENOSYS; +#endif +} diff --git a/include/zephyr/drivers/flash.h b/include/zephyr/drivers/flash.h index ecc0f4d0e29bcb..7ceea4a5b254e6 100644 --- a/include/zephyr/drivers/flash.h +++ b/include/zephyr/drivers/flash.h @@ -141,6 +141,11 @@ typedef int (*flash_api_write)(const struct device *dev, off_t offset, * the driver, with the driver responsible for ensuring the "erase-protect" * after the operation completes (successfully or not) matches the erase-protect * state when the operation was started. + * + * The callback is optional for RAM non-volatile devices, which do not + * require erase by design, but may be provided if it allows device to + * work more effectively, or if device has a support for internal fill + * operation the erase in driver uses. */ typedef int (*flash_api_erase)(const struct device *dev, off_t offset, size_t size); @@ -278,12 +283,19 @@ static inline int z_impl_flash_write(const struct device *dev, off_t offset, * Any necessary erase protection management is performed by the driver * erase implementation itself. * + * The function should be used only for devices that are really + * explicit erase devices; in case when code relies on erasing + * device, i.e. setting it to erase-value, prior to some operations, + * but should work with explicit erase and RAM non-volatile devices, + * then flash_flatten should rather be used. + * * @param dev : flash device * @param offset : erase area starting offset * @param size : size of area to be erased * * @return 0 on success, negative errno code on fail. * + * @see flash_flatten() * @see flash_get_page_info_by_offs() * @see flash_get_page_info_by_idx() */ @@ -292,15 +304,59 @@ __syscall int flash_erase(const struct device *dev, off_t offset, size_t size); static inline int z_impl_flash_erase(const struct device *dev, off_t offset, size_t size) { + int rc = -ENOSYS; + const struct flash_driver_api *api = (const struct flash_driver_api *)dev->api; - int rc; - rc = api->erase(dev, offset, size); + if (api->erase != NULL) { + rc = api->erase(dev, offset, size); + } return rc; } +__syscall int flash_fill(const struct device *dev, uint8_t val, off_t offset, size_t size); + +/** + * @brief Erase part or all of a flash memory or level it + * + * If device is explicit erase type device or device driver provides erase + * callback, the callback of the device is called, in which it behaves + * the same way as flash_erase. + * If a device is does not require explicit erase, either because + * it has no erase at all or has auto-erase/erase-on-write, + * and does not provide erase callback then erase is emulated by + * leveling selected device memory area with erase_value assigned to + * device. + * + * Erase page offset and size are constrains of paged, explicit erase devices, + * but can be relaxed with devices without such requirement, which means that + * it is up to user code to make sure they are correct as the function + * will return on, if these constrains are not met, -EINVAL for + * paged device, but may succeed on non-explicit erase devices. + * For RAM non-volatile devices the erase pages are emulated, + * at this point, to allow smooth transition for code relying on + * device being paged to function properly; but this is completely + * software constrain. + * + * Generally: if your code previously required device to be erase + * prior to some actions to work, replace flash_erase calls with this + * function; but if your code can work with non-volatile RAM type devices, + * without emulating erase, you should rather have different path + * of execution for page-erase, i.e. Flash, devices and call + * flash_erase for them. + * + * @param dev : flash device + * @param offset : erase area starting offset + * @param size : size of area to be erased + * + * @return 0 on success, negative errno code on fail. + * + * @see flash_erase() + */ +__syscall int flash_flatten(const struct device *dev, off_t offset, size_t size); + struct flash_pages_info { off_t start_offset; /* offset from the base of flash address */ size_t size; diff --git a/tests/drivers/flash/common/src/main.c b/tests/drivers/flash/common/src/main.c index 8b6bb80ecab8bd..4eeb4920993724 100644 --- a/tests/drivers/flash/common/src/main.c +++ b/tests/drivers/flash/common/src/main.c @@ -180,4 +180,78 @@ ZTEST(flash_driver, test_read_unaligned_address) } } +ZTEST(flash_driver, test_flash_fill) +{ + uint8_t buf[EXPECTED_SIZE]; + int rc; + off_t i; + + if (IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && ebw_required) { + /* Erase a nb of pages aligned to the EXPECTED_SIZE */ + rc = flash_erase(flash_dev, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + + zassert_equal(rc, 0, "Flash memory not properly erased"); + } else { + rc = flash_fill(flash_dev, 0x55, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + zassert_equal(rc, 0, "Leveling memory with fill failed\n"); + } + + /* Fill the device with 0xaa */ + rc = flash_fill(flash_dev, 0xaa, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + zassert_equal(rc, 0, "Fill failed\n"); + + rc = flash_read(flash_dev, TEST_AREA_OFFSET, + buf, EXPECTED_SIZE); + zassert_equal(rc, 0, "Cannot read flash"); + + for (i = 0; i < EXPECTED_SIZE; i++) { + if (buf[i] != 0xaa) { + break; + } + } + zassert_equal(i, EXPECTED_SIZE, "Expected device to be filled wth 0xaa"); +} + +ZTEST(flash_driver, test_flash_flatten) +{ + uint8_t buf[EXPECTED_SIZE]; + int rc; + off_t i; + + rc = flash_flatten(flash_dev, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + + zassert_equal(rc, 0, "Flash not leveled not properly erased"); + + /* Fill the device with 0xaa */ + rc = flash_fill(flash_dev, 0xaa, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + zassert_equal(rc, 0, "Fill failed\n"); + + rc = flash_read(flash_dev, TEST_AREA_OFFSET, + buf, EXPECTED_SIZE); + zassert_equal(rc, 0, "Cannot read flash"); + + for (i = 0; i < EXPECTED_SIZE; i++) { + if (buf[i] != 0xaa) { + break; + } + } + zassert_equal(i, EXPECTED_SIZE, "Expected device to be filled wth 0xaa"); +} + + ZTEST_SUITE(flash_driver, NULL, flash_driver_setup, NULL, NULL, NULL); From a5f7ceff812e73a17b2720586abf367c0ee97f5c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 7 Mar 2024 22:43:44 +0000 Subject: [PATCH 035/981] storage/flash_map: Add flash_area_flatten Add equivalent of flash_erase, from Flash API, to Flash Map API; idea is the same: function tries to erase area if driver provides erase function, otherwise writes erase_value across the defined area. Signed-off-by: Dominik Ermel --- include/zephyr/storage/flash_map.h | 23 +++++++++ subsys/storage/flash_map/flash_map.c | 9 ++++ tests/subsys/storage/flash_map/src/main.c | 61 +++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/include/zephyr/storage/flash_map.h b/include/zephyr/storage/flash_map.h index b03628afc93ec3..937e242830ae39 100644 --- a/include/zephyr/storage/flash_map.h +++ b/include/zephyr/storage/flash_map.h @@ -187,6 +187,29 @@ int flash_area_write(const struct flash_area *fa, off_t off, const void *src, */ int flash_area_erase(const struct flash_area *fa, off_t off, size_t len); +/** + * @brief Erase flash area or fill with erase-value + * + * On program-erase devices this function behaves exactly like flash_area_erase. + * On RAM non-volatile device it will call erase, if driver provides such + * callback, or will fill given range with erase-value defined by driver. + * This function should be only used by code that has not been written + * to directly support devices that do not require erase and rely on + * device being erased prior to some operations. + * Note that emulated erase, on devices that do not require, is done + * via write, which affects endurance of device. + * + * @see flash_area_erase() + * @see flash_flatten() + * + * @param[in] fa Flash area + * @param[in] off Offset relative from beginning of flash area. + * @param[in] len Number of bytes to be erase + * + * @return 0 on success, negative errno code on fail. + */ +int flash_area_flatten(const struct flash_area *fa, off_t off, size_t len); + /** * @brief Get write block size of the flash area * diff --git a/subsys/storage/flash_map/flash_map.c b/subsys/storage/flash_map/flash_map.c index 79be7cae6d661b..471b33358c9489 100644 --- a/subsys/storage/flash_map/flash_map.c +++ b/subsys/storage/flash_map/flash_map.c @@ -82,6 +82,15 @@ int flash_area_erase(const struct flash_area *fa, off_t off, size_t len) return flash_erase(fa->fa_dev, fa->fa_off + off, len); } +int flash_area_flatten(const struct flash_area *fa, off_t off, size_t len) +{ + if (!is_in_flash_area_bounds(fa, off, len)) { + return -EINVAL; + } + + return flash_flatten(fa->fa_dev, fa->fa_off + off, len); +} + uint32_t flash_area_align(const struct flash_area *fa) { return flash_get_write_block_size(fa->fa_dev); diff --git a/tests/subsys/storage/flash_map/src/main.c b/tests/subsys/storage/flash_map/src/main.c index e66f6ac7e0f133..18fea4b2421fd2 100644 --- a/tests/subsys/storage/flash_map/src/main.c +++ b/tests/subsys/storage/flash_map/src/main.c @@ -202,4 +202,65 @@ ZTEST(flash_map, test_fixed_partition_node_macros) DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(SLOT1_PARTITION_NODE))); } +ZTEST(flash_map, test_flash_area_erase_and_flatten) +{ + int i; + bool erased = true; + int rc; + const struct flash_area *fa; + const struct device *flash_dev; + + rc = flash_area_open(SLOT1_PARTITION_ID, &fa); + zassert_true(rc == 0, "flash_area_open() fail"); + + /* First erase the area so it's ready for use. */ + flash_dev = flash_area_get_device(fa); + + rc = flash_erase(flash_dev, fa->fa_off, fa->fa_size); + zassert_true(rc == 0, "flash area erase fail"); + + rc = flash_fill(flash_dev, 0xaa, fa->fa_off, fa->fa_size); + zassert_true(rc == 0, "flash device fill fail"); + + rc = flash_area_erase(fa, 0, fa->fa_size); + zassert_true(rc == 0, "flash area erase fail"); + + /* we work under assumption that flash_fill is working and tested */ + for (i = 0; erased && i < fa->fa_size; ++i) { + uint8_t buf[32]; + int chunk = MIN(sizeof(buf), fa->fa_size - i); + + rc = flash_read(flash_dev, i, buf, chunk); + zassert_equal(rc, 0, "Unexpected read fail"); + for (int ii = 0; ii < chunk; ++ii, ++i) { + if (buf[ii] != flash_area_erased_val(fa)) { + erased = false; + break; + } + } + } + zassert_true(erased, "Erase failed at index %d", i); + + rc = flash_fill(flash_dev, 0xaa, fa->fa_off, fa->fa_size); + zassert_true(rc == 0, "flash device fill fail"); + + rc = flash_area_flatten(fa, 0, fa->fa_size); + + erased = true; + for (i = 0; erased && i < fa->fa_size; ++i) { + uint8_t buf[32]; + int chunk = MIN(sizeof(buf), fa->fa_size - i); + + rc = flash_read(flash_dev, i, buf, chunk); + zassert_equal(rc, 0, "Unexpected read fail"); + for (int ii = 0; ii < chunk; ++ii, ++i) { + if (buf[ii] != flash_area_erased_val(fa)) { + erased = false; + break; + } + } + } + zassert_true(erased, "Flatten/Erase failed at index %d", i); +} + ZTEST_SUITE(flash_map, NULL, NULL, NULL, NULL, NULL); From ff81b5244833fc7d163f0d26ed35538c9bb577f7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 6 Mar 2024 21:53:44 +0000 Subject: [PATCH 036/981] drivers/flash_simulator: Add support for non-erase device The commit adds support for testing non-explicite-erase device on Flash Simulator. This is addition to already supported explicit erase before write, aka Flash, type of device behaviour. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.simulator | 20 +++ drivers/flash/flash_simulator.c | 15 +- .../flash_simulator/flash_sim_impl/src/main.c | 160 ++++++++++++++++++ .../flash_sim_impl/testcase.yaml | 11 ++ 4 files changed, 205 insertions(+), 1 deletion(-) diff --git a/drivers/flash/Kconfig.simulator b/drivers/flash/Kconfig.simulator index e32a2a72bb0dad..fd75479b316829 100644 --- a/drivers/flash/Kconfig.simulator +++ b/drivers/flash/Kconfig.simulator @@ -22,12 +22,32 @@ config FLASH_SIMULATOR_UNALIGNED_READ Disable this option only if you want to simulate a specific FLASH interface that requires aligned read access. +config FLASH_SIMULATOR_EXPLICIT_ERASE + bool "Program-erase device" + select FLASH_HAS_EXPLICIT_ERASE + default y + help + Explicit erase (non-erase-on-write) Flash, which is device that requires erase + to erase-value prior to write as it only allows to change bits from erase-value + to the opposite. + +config FLASH_SIMULATOR_RAMLIKE + bool + default y if !FLASH_SIMULATOR_EXPLICIT_ERASE + select FLASH_HAS_NO_EXPLICIT_ERASE + select FLASH_SIMULATOR_DOUBLE_WRITES + help + This is used for setting FLASH_HAS_NO_EXPLICIT_ERASE. + config FLASH_SIMULATOR_DOUBLE_WRITES bool "Allow program units to be programmed more than once" help If selected, writing to a non-erased program unit will succeed, otherwise, it will return an error. Keep in mind that write operations can only change value of a bit from erase-value to the opposite. + This option does not impact FLASH_SIMULATOR_RAMLIKE. + In case when FLASH_SIMULATOR_EXPLICIT_ERASE is selected multiple writes to the same bit + but only change from erase-value to opposite will be registered. config FLASH_SIMULATOR_SIMULATE_TIMING bool "Hardware timing simulation" diff --git a/drivers/flash/flash_simulator.c b/drivers/flash/flash_simulator.c index effd53c1f2b30d..3a7d578a250a6d 100644 --- a/drivers/flash/flash_simulator.c +++ b/drivers/flash/flash_simulator.c @@ -162,7 +162,12 @@ static const struct flash_driver_api flash_sim_api; static const struct flash_parameters flash_sim_parameters = { .write_block_size = FLASH_SIMULATOR_PROG_UNIT, - .erase_value = FLASH_SIMULATOR_ERASE_VALUE + .erase_value = FLASH_SIMULATOR_ERASE_VALUE, + .caps = { +#if !defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) + .no_explicit_erase = false, +#endif + }, }; static int flash_range_is_valid(const struct device *dev, off_t offset, @@ -226,8 +231,12 @@ static int flash_sim_write(const struct device *dev, const off_t offset, FLASH_SIM_STATS_INC(flash_sim_stats, flash_write_calls); +#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) /* check if any unit has been already programmed */ memset(buf, FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf)); +#else + memcpy(buf, MOCK_FLASH(offset), sizeof(buf)); +#endif for (uint32_t i = 0; i < len; i += FLASH_SIMULATOR_PROG_UNIT) { if (memcmp(buf, MOCK_FLASH(offset + i), sizeof(buf))) { FLASH_SIM_STATS_INC(flash_sim_stats, double_writes); @@ -265,10 +274,14 @@ static int flash_sim_write(const struct device *dev, const off_t offset, #endif /* CONFIG_FLASH_SIMULATOR_STATS */ /* only pull bits to zero */ +#if IS_ENABLED(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) #if FLASH_SIMULATOR_ERASE_VALUE == 0xFF *(MOCK_FLASH(offset + i)) &= *((uint8_t *)data + i); #else *(MOCK_FLASH(offset + i)) |= *((uint8_t *)data + i); +#endif +#else + *(MOCK_FLASH(offset + i)) = *((uint8_t *)data + i); #endif } diff --git a/tests/drivers/flash_simulator/flash_sim_impl/src/main.c b/tests/drivers/flash_simulator/flash_sim_impl/src/main.c index 69871c2b8aab93..ac90a821410e49 100644 --- a/tests/drivers/flash_simulator/flash_sim_impl/src/main.c +++ b/tests/drivers/flash_simulator/flash_sim_impl/src/main.c @@ -8,6 +8,10 @@ #include #include +/* Warning: The test has been written for testing boards with single + * instance of Flash Simulator device only. + */ + /* configuration derived from DT */ #ifdef CONFIG_ARCH_POSIX #define SOC_NV_FLASH_NODE DT_CHILD(DT_INST(0, zephyr_sim_flash), flash_0) @@ -75,6 +79,44 @@ static void test_check_pattern32(off_t start, uint32_t (*pattern_gen)(void), } } +/* ret < 0 is errno; ret == 1 is bad value in flash */ +static int test_check_erase(const struct device *dev, off_t offset, size_t size) +{ + uint8_t buf[FLASH_SIMULATOR_PROG_UNIT]; + int rc; + int i = 0; + + BUILD_ASSERT(sizeof(buf) >= FLASH_SIMULATOR_PROG_UNIT); + + i = 0; + while (i < size) { + size_t chunk = MIN(size - i, sizeof(buf)); + /* The memset is done to set buf to something else than + * FLASH_SIMULATOR_ERASE_VALUE, as we are trying to chek + * whether that is what is now in the memory. + */ + memset(buf, ~FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf)); + rc = flash_read(flash_dev, offset + i, + buf, chunk); + if (rc < 0) { + TC_PRINT("Unexpected flash_read fail @ %ld", + (long)(offset + i)); + return rc; + } + do { + if ((uint8_t)buf[i & (sizeof(buf) - 1)] != + (uint8_t)FLASH_SIMULATOR_ERASE_VALUE) { + TC_PRINT("Flash not erased at %ld\n", + (long)(offset + i)); + return 1; + } + ++i; + --chunk; + } while (chunk); + } + return 0; +} + /* Get access to the device and erase it ready for testing*/ static void test_init(void) { @@ -259,6 +301,8 @@ ZTEST(flash_sim_api, test_align) zassert_equal(-EINVAL, rc, "Unexpected error code (%d)", rc); } +#if !IS_ENABLED(CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES) && \ + !IS_ENABLED(CONFIG_FLASH_SIMULATOR_RAMLIKE) ZTEST(flash_sim_api, test_double_write) { int rc; @@ -282,6 +326,122 @@ ZTEST(flash_sim_api, test_double_write) &data, sizeof(data)); zassert_equal(-EIO, rc, "Unexpected error code (%d)", rc); } +#endif + +#if IS_ENABLED(CONFIG_FLASH_SIMULATOR_RAMLIKE) +ZTEST(flash_sim_api, test_ramlike) +{ + /* Within code below there is assumption that the src size is + * equal or greater than the FLASH_SIMULATOR_PROG_UNIT + * (write-block-size) of device. + */ + const uint8_t src[] = "Hello world! This is test string"; + uint8_t buf[FLASH_SIMULATOR_PROG_UNIT]; + /* Round up to next write-block-size */ + int max = (sizeof(src) + FLASH_SIMULATOR_PROG_UNIT - 1) & + ~(FLASH_SIMULATOR_PROG_UNIT - 1); + int rc; + int i = 0; + int is = 0; /* The index within src */ + + BUILD_ASSERT(sizeof(src) >= FLASH_SIMULATOR_PROG_UNIT); + + /* Scrub memory with something constant */ + memset(buf, FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf)); + while (i < max) { + rc = flash_write(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i, + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_write should succeed"); + i += sizeof(buf); + } + + /* Check the scrubbing */ + zassert_equal(0, test_check_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, max), + "Area not erased"); + + /* Now write something new */ + i = 0; + while (i < max) { + do { + buf[i & (sizeof(buf) - 1)] = src[is]; + ++i; + ++is; + + /* Continue writing from the beginning of the src */ + if (is >= sizeof(src)) { + is = 0; + } + } while (i & (sizeof(buf) - 1)); + rc = flash_write(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i - sizeof(buf), + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_write should succeed"); + } + + /* Check the write */ + i = 0; + is = 0; + while (i < max) { + rc = flash_read(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i, + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_read should succeed"); + do { + zassert_equal((uint8_t)src[is], (uint8_t)buf[i & (sizeof(buf) - 1)], + "Expected src and buf to match at index %d\n", i); + ++i; + ++is; + /* Src has wrapped around */ + if (is >= sizeof(src)) { + is = 0; + } + } while (i & (sizeof(buf) - 1)); + zassert_equal(0, rc, "Unexpected value read"); + } + + /* Because we are checking random access writes, we are now going to + * write binary not of the same data we have just written. If this would be + * program-erase type memory, where you can only change from erase value + * to opposite, such write would render incorrect data in memory, + * but this is random access device so we should get exactly what we write. + */ + i = 0; + is = 0; + while (i < max) { + do { + buf[i & (sizeof(buf) - 1)] = ~src[is]; + ++i; + ++is; + + /* Continue writing from the beginning of the src */ + if (is >= sizeof(src)) { + is = 0; + } + } while (i & (sizeof(buf) - 1)); + rc = flash_write(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i - sizeof(buf), + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_write should succeed"); + } + + /* Check the write */ + i = 0; + is = 0; + while (i < max) { + rc = flash_read(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i, + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_read should succeed"); + do { + zassert_equal((uint8_t)~src[is], (uint8_t)buf[i & (sizeof(buf) - 1)], + "Expected src and buf to match at index %d\n", i); + ++i; + ++is; + /* Src has wrapped around */ + if (is >= sizeof(src)) { + is = 0; + } + } while (i & (sizeof(buf) - 1)); + zassert_equal(0, rc, "Unexpected value read"); + } +} +#endif ZTEST(flash_sim_api, test_get_erase_value) { diff --git a/tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml b/tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml index 11efcf49278c27..7f2fa5a4719206 100644 --- a/tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml +++ b/tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml @@ -13,6 +13,17 @@ tests: - nucleo_f411re integration_platforms: - qemu_x86 + drivers.flash.flash_simulator.ramlike: + extra_args: CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: + - qemu_x86 + - native_posix + - native_posix/native/64 + - native_sim + - native_sim/native/64 + - nucleo_f411re + integration_platforms: + - qemu_x86 drivers.flash.flash_simulator.qemu_erase_value_0x00: extra_args: DTC_OVERLAY_FILE=boards/qemu_x86_ev_0x00.overlay platform_allow: qemu_x86 From bbb7bbe46d9d537cedf3830bca864678560782c2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 7 Mar 2024 22:43:08 +0000 Subject: [PATCH 037/981] tests/flash_simulator: Test scenario for flash_flatten() The commit adds test scenarios for flash_fill() and flash_flatten() Flash API calls. Signed-off-by: Dominik Ermel --- .../flash_simulator/flash_sim_impl/src/main.c | 110 +++++++++++++++++- 1 file changed, 107 insertions(+), 3 deletions(-) diff --git a/tests/drivers/flash_simulator/flash_sim_impl/src/main.c b/tests/drivers/flash_simulator/flash_sim_impl/src/main.c index ac90a821410e49..87eff3986c4ba1 100644 --- a/tests/drivers/flash_simulator/flash_sim_impl/src/main.c +++ b/tests/drivers/flash_simulator/flash_sim_impl/src/main.c @@ -301,8 +301,8 @@ ZTEST(flash_sim_api, test_align) zassert_equal(-EINVAL, rc, "Unexpected error code (%d)", rc); } -#if !IS_ENABLED(CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES) && \ - !IS_ENABLED(CONFIG_FLASH_SIMULATOR_RAMLIKE) +#if defined(CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES) && \ + defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) ZTEST(flash_sim_api, test_double_write) { int rc; @@ -328,7 +328,7 @@ ZTEST(flash_sim_api, test_double_write) } #endif -#if IS_ENABLED(CONFIG_FLASH_SIMULATOR_RAMLIKE) +#if !defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) ZTEST(flash_sim_api, test_ramlike) { /* Within code below there is assumption that the src size is @@ -452,6 +452,110 @@ ZTEST(flash_sim_api, test_get_erase_value) FLASH_SIMULATOR_ERASE_VALUE); } +ZTEST(flash_sim_api, test_flash_fill) +{ + off_t i; + int rc; + uint8_t buf[FLASH_SIMULATOR_PROG_UNIT]; +#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) + rc = flash_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_erase should succeed"); +#else + rc = flash_fill(flash_dev, FLASH_SIMULATOR_ERASE_VALUE, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); +#endif + size_t size = FLASH_SIMULATOR_FLASH_SIZE; + + zassert_equal(0, test_check_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE), + "Area not erased"); + + rc = flash_fill(flash_dev, 0x55, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); + + /* Check if fill did work on both type of devices */ + i = 0; + size = FLASH_SIMULATOR_FLASH_SIZE; + while (i < FLASH_SIMULATOR_FLASH_SIZE) { + size_t chunk = MIN(size, FLASH_SIMULATOR_PROG_UNIT); + + memset(buf, FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf)); + rc = flash_read(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i, + buf, chunk); + zassert_equal(0, rc, "flash_read should succeed at offset %d", i); + do { + zassert_equal((uint8_t)buf[i & (sizeof(buf) - 1)], 0x55, + "Unexpected value at offset %d\n", i); + ++i; + --size; + --chunk; + } while (chunk); + } +} + +ZTEST(flash_sim_api, test_flash_flatten) +{ + int rc; +#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) + rc = flash_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_erase should succeed"); +#else + rc = flash_fill(flash_dev, FLASH_SIMULATOR_ERASE_VALUE, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); +#endif + /* Now fill the device with anything */ + rc = flash_fill(flash_dev, 0xaa, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); + + /* And erase */ + rc = flash_flatten(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_flatten should succeed"); + +#if !defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) + /* In case of RAM like devices, the erase may not be + * provided, in such case flash_flatten calls flash_fill + * with erase_value. + */ + struct device other; + struct flash_driver_api api; + + memcpy(&other, flash_dev, sizeof(other)); + other.api = &api; + memcpy(&api, flash_dev->api, sizeof(api)); + api.erase = NULL; + + /* Now fill the device with anything */ + rc = flash_fill(flash_dev, 0xaa, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); + + /* The erase is not implemented */ + rc = flash_erase(&other, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(-ENOSYS, rc, "Expected not implemented"); + + rc = flash_flatten(&other, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_flatten should succeed"); + + test_check_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + +#endif +} + #include ZTEST(flash_sim_api, test_get_mock) From 6d75bc519baaaf9bc85ce40fd67c219a0a9294bb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 16 Jan 2024 16:59:38 +0000 Subject: [PATCH 038/981] drivers/flash/nrf: Mark driver as FLASH_HAS_EXPLICIT_ERASE Select CONFIG_FLASH_HAS_EXPLICIT_ERASE for the NRF driver. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nrf | 1 + drivers/flash/soc_flash_nrf.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/flash/Kconfig.nrf b/drivers/flash/Kconfig.nrf index 769ccc7a51d523..48c4e0d3fb94b5 100644 --- a/drivers/flash/Kconfig.nrf +++ b/drivers/flash/Kconfig.nrf @@ -17,6 +17,7 @@ menuconfig SOC_FLASH_NRF depends on !FLASH_NRF_FORCE_ALT select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select NRFX_NVMC select MPU_ALLOW_FLASH_WRITE if ARM_MPU help diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index cc840309264e63..de9cfd423450db 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2023 Nordic Semiconductor ASA + * Copyright (c) 2017-2024 Nordic Semiconductor ASA * Copyright (c) 2016 Linaro Limited * Copyright (c) 2016 Intel Corporation * From 127bc5e35e28d412f9b9f214156e6d59d4fc0474 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 26 Feb 2024 19:52:45 +0000 Subject: [PATCH 039/981] drivers/flash/nrf_rram: Set no explicit erase capability to true NRF RRAM does not require erase prior to re-programming already written area. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nrf_rram | 1 + drivers/flash/soc_flash_nrf_rram.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/flash/Kconfig.nrf_rram b/drivers/flash/Kconfig.nrf_rram index a729b57bc288db..84214f809eb430 100644 --- a/drivers/flash/Kconfig.nrf_rram +++ b/drivers/flash/Kconfig.nrf_rram @@ -11,6 +11,7 @@ menuconfig SOC_FLASH_NRF_RRAM select NRFX_RRAMC select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_NO_EXPLICIT_ERASE select FLASH_NRF_FORCE_ALT select MPU_ALLOW_FLASH_WRITE if ARM_MPU help diff --git a/drivers/flash/soc_flash_nrf_rram.c b/drivers/flash/soc_flash_nrf_rram.c index 9e5e652ca5ed55..35a6c98862c699 100644 --- a/drivers/flash/soc_flash_nrf_rram.c +++ b/drivers/flash/soc_flash_nrf_rram.c @@ -309,6 +309,9 @@ static const struct flash_parameters *nrf_rram_get_parameters(const struct devic static const struct flash_parameters parameters = { .write_block_size = WRITE_LINE_SIZE, .erase_value = ERASE_VALUE, + .caps = { + .no_explicit_erase = true, + }, }; return ¶meters; From 0e970c83627015090fb4c2eafb1cf99b1ec85aa2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 11 Mar 2024 16:19:47 +0000 Subject: [PATCH 040/981] drivers/flash/nrf_mram: Set no explicit erase capability to true NRF MRAM does not require erase prior to re-programming already written area. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nrf_mram | 1 + drivers/flash/soc_flash_nrf_mram.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/flash/Kconfig.nrf_mram b/drivers/flash/Kconfig.nrf_mram index 0ef65864a622f8..be41cead07f185 100644 --- a/drivers/flash/Kconfig.nrf_mram +++ b/drivers/flash/Kconfig.nrf_mram @@ -10,6 +10,7 @@ config SOC_FLASH_NRF_MRAM depends on DT_HAS_NORDIC_MRAM_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_NO_EXPLICIT_ERASE imply MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enables Nordic Semiconductor flash driver for MRAM in direct write mode. diff --git a/drivers/flash/soc_flash_nrf_mram.c b/drivers/flash/soc_flash_nrf_mram.c index 9b33ee05d6f6cf..5d8215f7af30b3 100644 --- a/drivers/flash/soc_flash_nrf_mram.c +++ b/drivers/flash/soc_flash_nrf_mram.c @@ -142,6 +142,9 @@ static const struct flash_parameters *nrf_mram_get_parameters(const struct devic static const struct flash_parameters parameters = { .write_block_size = WRITE_BLOCK_SIZE, .erase_value = ERASE_VALUE, + .caps = { + .no_explicit_erase = true, + }, }; return ¶meters; From ea627fda7e3e10f12b6c17ede61eae43c13c8728 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 2 Feb 2024 13:46:29 +0000 Subject: [PATCH 041/981] drivers/flash: Add explict erase capability with proper values Add explicit_erase capability and set proper value to it, depending on type of a device. Select FLASH_HAS_EXPLICIT_ERASE by devices that have program-erase characteristics and FLASH_HAS_NO_EXPLICIT_ERASE, where needed. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.andes | 1 + drivers/flash/Kconfig.at45 | 1 + drivers/flash/Kconfig.b91 | 1 + drivers/flash/Kconfig.cadence_nand | 1 + drivers/flash/Kconfig.cadence_qspi_nor | 1 + drivers/flash/Kconfig.cc13xx_cc26xx | 1 + drivers/flash/Kconfig.esp32 | 1 + drivers/flash/Kconfig.gd32 | 1 + drivers/flash/Kconfig.gecko | 1 + drivers/flash/Kconfig.ifx_cat1 | 1 + drivers/flash/Kconfig.it8xxx2 | 1 + drivers/flash/Kconfig.lpc | 1 + drivers/flash/Kconfig.mcux | 4 ++++ drivers/flash/Kconfig.nios2_qspi | 1 + drivers/flash/Kconfig.npcx_fiu | 1 + drivers/flash/Kconfig.numaker | 1 + drivers/flash/Kconfig.nxp_s32 | 1 + drivers/flash/Kconfig.rpi_pico | 1 + drivers/flash/Kconfig.rv32m1 | 1 + drivers/flash/Kconfig.sam | 1 + drivers/flash/Kconfig.sam0 | 1 + drivers/flash/Kconfig.smartbond | 1 + drivers/flash/Kconfig.stm32 | 1 + drivers/flash/Kconfig.stm32_ospi | 1 + drivers/flash/Kconfig.stm32_qspi | 1 + drivers/flash/Kconfig.xmc4xxx | 1 + 26 files changed, 29 insertions(+) diff --git a/drivers/flash/Kconfig.andes b/drivers/flash/Kconfig.andes index d639cf20467e61..0a1a563519533e 100644 --- a/drivers/flash/Kconfig.andes +++ b/drivers/flash/Kconfig.andes @@ -12,6 +12,7 @@ menuconfig FLASH_ANDES_QSPI select FLASH_HAS_PAGE_LAYOUT select FLASH_JESD216 select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE depends on !SPI_NOR help Enable driver for Andes QSPI diff --git a/drivers/flash/Kconfig.at45 b/drivers/flash/Kconfig.at45 index c1c892e33fd80d..bf5c0add72c7dd 100644 --- a/drivers/flash/Kconfig.at45 +++ b/drivers/flash/Kconfig.at45 @@ -7,6 +7,7 @@ menuconfig SPI_FLASH_AT45 depends on DT_HAS_ATMEL_AT45_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select SPI help This driver can handle several instances of AT45 family chips that diff --git a/drivers/flash/Kconfig.b91 b/drivers/flash/Kconfig.b91 index 46a8b10e804bf3..a3f35da8581f3b 100644 --- a/drivers/flash/Kconfig.b91 +++ b/drivers/flash/Kconfig.b91 @@ -7,5 +7,6 @@ config SOC_FLASH_TELINK_B91 depends on DT_HAS_TELINK_B91_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables Telink B91 flash driver. diff --git a/drivers/flash/Kconfig.cadence_nand b/drivers/flash/Kconfig.cadence_nand index 52b7a1422b109a..436592aa2d8ef7 100644 --- a/drivers/flash/Kconfig.cadence_nand +++ b/drivers/flash/Kconfig.cadence_nand @@ -10,6 +10,7 @@ config FLASH_CDNS_NAND depends on DT_HAS_CDNS_NAND_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enable Cadence NAND support. diff --git a/drivers/flash/Kconfig.cadence_qspi_nor b/drivers/flash/Kconfig.cadence_qspi_nor index 0bc9a33402c653..4209b256cfdb93 100644 --- a/drivers/flash/Kconfig.cadence_qspi_nor +++ b/drivers/flash/Kconfig.cadence_qspi_nor @@ -7,6 +7,7 @@ config FLASH_CAD_QSPI_NOR depends on DT_HAS_CDNS_QSPI_NOR_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enable Cadence QSPI-NOR support. diff --git a/drivers/flash/Kconfig.cc13xx_cc26xx b/drivers/flash/Kconfig.cc13xx_cc26xx index 3abc4fc2d7d34e..e691dddb4727a6 100644 --- a/drivers/flash/Kconfig.cc13xx_cc26xx +++ b/drivers/flash/Kconfig.cc13xx_cc26xx @@ -7,6 +7,7 @@ config SOC_FLASH_CC13XX_CC26XX depends on DT_HAS_TI_CC13XX_CC26XX_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enables TI SimpleLink CC13xx/CC26xx flash controller driver. diff --git a/drivers/flash/Kconfig.esp32 b/drivers/flash/Kconfig.esp32 index 3d5790d4a2f52c..4da80bce0c0fdd 100644 --- a/drivers/flash/Kconfig.esp32 +++ b/drivers/flash/Kconfig.esp32 @@ -7,6 +7,7 @@ config SOC_FLASH_ESP32 depends on DT_HAS_ESPRESSIF_ESP32_FLASH_CONTROLLER_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE help Enable ESP32 internal flash driver. diff --git a/drivers/flash/Kconfig.gd32 b/drivers/flash/Kconfig.gd32 index c3c86bf35795ae..c4d8921a6aad03 100644 --- a/drivers/flash/Kconfig.gd32 +++ b/drivers/flash/Kconfig.gd32 @@ -7,6 +7,7 @@ config SOC_FLASH_GD32 depends on (GD32_NV_FLASH_V1 || GD32_NV_FLASH_V2 || GD32_NV_FLASH_V3) select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the GigaDevice GD32 flash driver. diff --git a/drivers/flash/Kconfig.gecko b/drivers/flash/Kconfig.gecko index 903b08373b32e9..fc5478eae2698c 100644 --- a/drivers/flash/Kconfig.gecko +++ b/drivers/flash/Kconfig.gecko @@ -10,6 +10,7 @@ config SOC_FLASH_GECKO select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT select SOC_GECKO_MSC + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable Silicon Labs Gecko series internal flash driver. diff --git a/drivers/flash/Kconfig.ifx_cat1 b/drivers/flash/Kconfig.ifx_cat1 index f8871d4d1e30d7..4964258c4ec20d 100644 --- a/drivers/flash/Kconfig.ifx_cat1 +++ b/drivers/flash/Kconfig.ifx_cat1 @@ -12,6 +12,7 @@ config FLASH_INFINEON_CAT1 select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED select USE_INFINEON_FLASH + select FLASH_HAS_EXPLICIT_ERASE help Enable the Flash driver for Infineon CAT1 family. diff --git a/drivers/flash/Kconfig.it8xxx2 b/drivers/flash/Kconfig.it8xxx2 index 50b881335a4fed..ef0307f65a39e8 100644 --- a/drivers/flash/Kconfig.it8xxx2 +++ b/drivers/flash/Kconfig.it8xxx2 @@ -10,6 +10,7 @@ config SOC_FLASH_ITE_IT8XXX2 select SOC_IT8XXX2_USE_ILM select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select HAS_FLASH_LOAD_OFFSET help The flash driver includes support for read, write and diff --git a/drivers/flash/Kconfig.lpc b/drivers/flash/Kconfig.lpc index 379a4cdaadc70b..4d1fd1940e0f1d 100644 --- a/drivers/flash/Kconfig.lpc +++ b/drivers/flash/Kconfig.lpc @@ -8,6 +8,7 @@ config SOC_FLASH_LPC DT_HAS_NXP_IAP_FMC54_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables the LPC IAP flash shim driver. WARNING: This driver will disable the system interrupts for diff --git a/drivers/flash/Kconfig.mcux b/drivers/flash/Kconfig.mcux index 2cf9eac494d282..7b3df8361076bc 100644 --- a/drivers/flash/Kconfig.mcux +++ b/drivers/flash/Kconfig.mcux @@ -11,6 +11,7 @@ config SOC_FLASH_MCUX DT_HAS_NXP_IAP_MSF1_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enables the MCUX flash shim driver. @@ -41,6 +42,7 @@ config FLASH_MCUX_FLEXSPI_NOR depends on DT_HAS_NXP_IMX_FLEXSPI_NOR_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select FLASH_JESD216 select MEMC select MEMC_MCUX_FLEXSPI @@ -51,6 +53,7 @@ config FLASH_MCUX_FLEXSPI_MX25UM51345G depends on DT_HAS_NXP_IMX_FLEXSPI_MX25UM51345G_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MEMC select MEMC_MCUX_FLEXSPI @@ -60,6 +63,7 @@ config FLASH_MCUX_FLEXSPI_HYPERFLASH depends on DT_HAS_NXP_IMX_FLEXSPI_HYPERFLASH_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MEMC select MEMC_MCUX_FLEXSPI diff --git a/drivers/flash/Kconfig.nios2_qspi b/drivers/flash/Kconfig.nios2_qspi index bcad6d9e50dd1e..ab834b5b956354 100644 --- a/drivers/flash/Kconfig.nios2_qspi +++ b/drivers/flash/Kconfig.nios2_qspi @@ -6,5 +6,6 @@ config SOC_FLASH_NIOS2_QSPI depends on HAS_ALTERA_HAL depends on DT_HAS_ALTR_NIOS2_QSPI_NOR_ENABLED select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables the Nios-II QSPI flash driver. diff --git a/drivers/flash/Kconfig.npcx_fiu b/drivers/flash/Kconfig.npcx_fiu index e4ac74c9d444ea..9d464f48bb78c5 100644 --- a/drivers/flash/Kconfig.npcx_fiu +++ b/drivers/flash/Kconfig.npcx_fiu @@ -18,6 +18,7 @@ config FLASH_NPCX_FIU_NOR depends on FLASH_NPCX_FIU_QSPI select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select FLASH_JESD216 select FLASH_HAS_EX_OP help diff --git a/drivers/flash/Kconfig.numaker b/drivers/flash/Kconfig.numaker index 98d4790589d3fe..4ab0f46271dc38 100644 --- a/drivers/flash/Kconfig.numaker +++ b/drivers/flash/Kconfig.numaker @@ -8,6 +8,7 @@ config SOC_FLASH_NUMAKER default y select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select HAS_NUMAKER_FMC depends on DT_HAS_NUVOTON_NUMAKER_FMC_ENABLED help diff --git a/drivers/flash/Kconfig.nxp_s32 b/drivers/flash/Kconfig.nxp_s32 index 08a96f1cec9bff..47db1ab654eea4 100644 --- a/drivers/flash/Kconfig.nxp_s32 +++ b/drivers/flash/Kconfig.nxp_s32 @@ -9,6 +9,7 @@ config FLASH_NXP_S32_QSPI_NOR select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED select FLASH_JESD216 + select FLASH_HAS_EXPLICIT_ERASE help Enable the Flash driver for a NOR Serial Flash Memory device connected to an NXP S32 QSPI bus. diff --git a/drivers/flash/Kconfig.rpi_pico b/drivers/flash/Kconfig.rpi_pico index 4d7fee169417f4..b41cd843c0899e 100644 --- a/drivers/flash/Kconfig.rpi_pico +++ b/drivers/flash/Kconfig.rpi_pico @@ -8,6 +8,7 @@ config FLASH_RPI_PICO depends on DT_HAS_RASPBERRYPI_PICO_FLASH_CONTROLLER_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select PICOSDK_USE_FLASH help Enable Raspberry Pi Pico flash driver. diff --git a/drivers/flash/Kconfig.rv32m1 b/drivers/flash/Kconfig.rv32m1 index 0dd7f290129181..46ada40d7c3f34 100644 --- a/drivers/flash/Kconfig.rv32m1 +++ b/drivers/flash/Kconfig.rv32m1 @@ -7,6 +7,7 @@ config SOC_FLASH_RV32M1 depends on DT_HAS_OPENISA_RV32M1_FTFE_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables the RV32M1 flash shim driver. WARNING: This driver will disable the system interrupts for diff --git a/drivers/flash/Kconfig.sam b/drivers/flash/Kconfig.sam index bb014d65279900..1e30636390d0fc 100644 --- a/drivers/flash/Kconfig.sam +++ b/drivers/flash/Kconfig.sam @@ -9,6 +9,7 @@ config SOC_FLASH_SAM depends on DT_HAS_ATMEL_SAM_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the Atmel SAM series internal flash driver. diff --git a/drivers/flash/Kconfig.sam0 b/drivers/flash/Kconfig.sam0 index accaa30d3039dd..f285aa868f8472 100644 --- a/drivers/flash/Kconfig.sam0 +++ b/drivers/flash/Kconfig.sam0 @@ -9,6 +9,7 @@ menuconfig SOC_FLASH_SAM0 depends on DT_HAS_ATMEL_SAM0_NVMCTRL_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the Atmel SAM0 series internal flash driver. diff --git a/drivers/flash/Kconfig.smartbond b/drivers/flash/Kconfig.smartbond index 3cc587ba7e1979..5d5dbd6a98e369 100644 --- a/drivers/flash/Kconfig.smartbond +++ b/drivers/flash/Kconfig.smartbond @@ -7,6 +7,7 @@ config SOC_FLASH_SMARTBOND depends on DT_HAS_RENESAS_SMARTBOND_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable flash driver for Renesas SmartBond(tm) MCU family. diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index 72481c5ae6ed9c..9caf7a04de8502 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -12,6 +12,7 @@ config SOC_FLASH_STM32 select FLASH_HAS_DRIVER_ENABLED default y select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU select USE_STM32_HAL_FLASH if BT_STM32WBA select USE_STM32_HAL_FLASH_EX if BT_STM32WBA diff --git a/drivers/flash/Kconfig.stm32_ospi b/drivers/flash/Kconfig.stm32_ospi index 305fcfac76d13d..2cc2ffcab5c00a 100644 --- a/drivers/flash/Kconfig.stm32_ospi +++ b/drivers/flash/Kconfig.stm32_ospi @@ -17,6 +17,7 @@ config FLASH_STM32_OSPI select FLASH_HAS_DRIVER_ENABLED select FLASH_JESD216 select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select DMA if $(DT_STM32_OCTOSPI_1_HAS_DMA) || $(DT_STM32_OCTOSPI_2_HAS_DMA) select USE_STM32_HAL_DMA if $(DT_STM32_OCTOSPI_1_HAS_DMA) || \ $(DT_STM32_OCTOSPI_2_HAS_DMA) diff --git a/drivers/flash/Kconfig.stm32_qspi b/drivers/flash/Kconfig.stm32_qspi index c97be5ef354b4c..4aeeaf3e2ee34d 100644 --- a/drivers/flash/Kconfig.stm32_qspi +++ b/drivers/flash/Kconfig.stm32_qspi @@ -15,6 +15,7 @@ config FLASH_STM32_QSPI select FLASH_HAS_DRIVER_ENABLED select FLASH_JESD216 select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select DMA if $(DT_STM32_QUADSPI_HAS_DMA) select USE_STM32_HAL_DMA if $(DT_STM32_QUADSPI_HAS_DMA) help diff --git a/drivers/flash/Kconfig.xmc4xxx b/drivers/flash/Kconfig.xmc4xxx index 60e5f08a759ef0..eff7b1e5679e9a 100644 --- a/drivers/flash/Kconfig.xmc4xxx +++ b/drivers/flash/Kconfig.xmc4xxx @@ -7,5 +7,6 @@ config SOC_FLASH_XMC4XXX depends on DT_HAS_INFINEON_XMC4XXX_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables XMC4XXX flash driver. From 3c24e1a530542b5c49e706fd4ac18753d26112a7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 2 Feb 2024 13:47:09 +0000 Subject: [PATCH 042/981] drivers/flash/Ambiq: Set erase capabilities, depending on SoC The commit selects HAS_NO_EXPLICIT_ERASE for Apollo4, with MRAM, and HAS_EXPLICIT_ERASE for Apollo3 which has Flash, for a driver that shares code between SoCs. In case of Apollo4 the no_explicit_erase capability is set to true, while it remains false for Apollo3. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.ambiq | 2 ++ drivers/flash/flash_ambiq.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/drivers/flash/Kconfig.ambiq b/drivers/flash/Kconfig.ambiq index 5ce028bba9664d..da0df1fcdab738 100644 --- a/drivers/flash/Kconfig.ambiq +++ b/drivers/flash/Kconfig.ambiq @@ -8,6 +8,8 @@ config FLASH_AMBIQ select AMBIQ_HAL select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_NO_EXPLICIT_ERASE if SOC_SERIES_APOLLO4X + select FLASH_HAS_EXPLICIT_ERASE if SOC_SERIES_APOLLO3X help Enables Ambiq flash driver on MRAM (e.g. Apollo4x) or flash (e.g. Apollo3x). diff --git a/drivers/flash/flash_ambiq.c b/drivers/flash/flash_ambiq.c index 30ce8524045104..b496790b958682 100644 --- a/drivers/flash/flash_ambiq.c +++ b/drivers/flash/flash_ambiq.c @@ -48,6 +48,11 @@ static struct k_sem flash_ambiq_sem; static const struct flash_parameters flash_ambiq_parameters = { .write_block_size = FLASH_WRITE_BLOCK_SIZE, .erase_value = FLASH_ERASE_BYTE, +#if defined(CONFIG_SOC_SERIES_APOLLO4X) + .caps = { + .no_explicit_erase = true, + }, +#endif }; static bool flash_ambiq_valid_range(off_t offset, size_t len) From 294187b576434dcff77a363d99bcb9893b853f2e Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 5 Feb 2024 20:15:30 +0000 Subject: [PATCH 043/981] flash/spi_nor: Mark driver with FLASH_HAS_EXPLICIT_ERASE Sets the Kconfig CONFIG_FLASH_HAS_EXPLICIT_ERASE. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nor | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/flash/Kconfig.nor b/drivers/flash/Kconfig.nor index 8263f7f6785da3..eed33c8e1807f9 100644 --- a/drivers/flash/Kconfig.nor +++ b/drivers/flash/Kconfig.nor @@ -1,4 +1,6 @@ # Copyright (c) 2018 Savoir-Faire Linux. +# Copyright (c) 2024 Nordic Semiconductor ASA +# # SPDX-License-Identifier: Apache-2.0 menuconfig SPI_NOR @@ -6,6 +8,7 @@ menuconfig SPI_NOR default y depends on DT_HAS_JEDEC_SPI_NOR_ENABLED select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select FLASH_HAS_PAGE_LAYOUT select FLASH_JESD216 select FLASH_HAS_EX_OP From 4fd503adacaa2f7d38b7336656544da6c148acd3 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 5 Feb 2024 21:05:36 +0000 Subject: [PATCH 044/981] drivers/flashdisk: Remove erase for devices that do not require it No erase when not needed by device. Signed-off-by: Dominik Ermel --- drivers/disk/flashdisk.c | 64 ++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/drivers/disk/flashdisk.c b/drivers/disk/flashdisk.c index 6336ad4dfd03e7..4c9d65ee7a634d 100644 --- a/drivers/disk/flashdisk.c +++ b/drivers/disk/flashdisk.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016 Intel Corporation. - * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * Copyright (c) 2022-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,11 @@ #include LOG_MODULE_REGISTER(flashdisk, CONFIG_FLASHDISK_LOG_LEVEL); +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && \ + defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) +#define DISK_ERASE_RUNTIME_CHECK +#endif + struct flashdisk_data { struct disk_info info; struct k_mutex lock; @@ -32,11 +37,43 @@ struct flashdisk_data { off_t cached_addr; bool cache_valid; bool cache_dirty; + bool erase_required; }; #define GET_SIZE_TO_BOUNDARY(start, block_size) \ (block_size - (start & (block_size - 1))) +/* + * The default block size is used for devices not requiring erase. + * It defaults to 512 as this is most widely used sector size + * on storage devices. + */ +#define DEFAULT_BLOCK_SIZE 512 + +static inline bool flashdisk_with_erase(const struct flashdisk_data *ctx) +{ + ARG_UNUSED(ctx); +#if CONFIG_FLASH_HAS_EXPLICIT_ERASE +#if CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE + return ctx->erase_required; +#else + return true; +#endif +#endif + return false; +} + +static inline void flashdisk_probe_erase(struct flashdisk_data *ctx) +{ +#if defined(DISK_ERASE_RUNTIME_CHECK) + ctx->erase_required = + flash_params_get_erase_cap(flash_get_parameters(ctx->info.dev)) & + FLASH_ERASE_C_EXPLICIT; +#else + ARG_UNUSED(ctx); +#endif +} + static int disk_flash_access_status(struct disk_info *disk) { LOG_DBG("status : %s", disk->dev ? "okay" : "no media"); @@ -54,13 +91,20 @@ static int flashdisk_init_runtime(struct flashdisk_data *ctx, struct flash_pages_info page; off_t offset; - rc = flash_get_page_info_by_offs(ctx->info.dev, ctx->offset, &page); - if (rc < 0) { - LOG_ERR("Error %d while getting page info", rc); - return rc; + flashdisk_probe_erase(ctx); + + if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT) && flashdisk_with_erase(ctx)) { + rc = flash_get_page_info_by_offs(ctx->info.dev, ctx->offset, &page); + if (rc < 0) { + LOG_ERR("Error %d while getting page info", rc); + return rc; + } + + ctx->page_size = page.size; + } else { + ctx->page_size = DEFAULT_BLOCK_SIZE; } - ctx->page_size = page.size; LOG_INF("Initialize device %s", ctx->info.name); LOG_INF("offset %lx, sector size %zu, page size %zu, volume size %zu", (long)ctx->offset, ctx->sector_size, ctx->page_size, ctx->size); @@ -71,7 +115,7 @@ static int flashdisk_init_runtime(struct flashdisk_data *ctx, return 0; } - if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT)) { + if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT) && flashdisk_with_erase(ctx)) { if (ctx->offset != page.start_offset) { LOG_ERR("Disk %s does not start at page boundary", ctx->info.name); @@ -213,8 +257,10 @@ static int flashdisk_cache_commit(struct flashdisk_data *ctx) return 0; } - if (flash_erase(ctx->info.dev, ctx->cached_addr, ctx->page_size) < 0) { - return -EIO; + if (flashdisk_with_erase(ctx)) { + if (flash_erase(ctx->info.dev, ctx->cached_addr, ctx->page_size) < 0) { + return -EIO; + } } /* write data to flash */ From d7a4b634f2b01dae9ff977b6b2e09043eaafb714 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 16:13:28 +0200 Subject: [PATCH 045/981] tests/flash_disk: Expand scenarios to cover no erase device The commit adds overlay for native_posix and modifies testcase.yaml to allow testing CONFIG_DISK_DRIVER_FLASH with device that do not have erase requirement. Signed-off-by: Dominik Ermel --- .../native_posix_no_explicit_erase.overlay | 32 +++++++++++++++++++ tests/drivers/disk/disk_access/testcase.yaml | 8 +++++ 2 files changed, 40 insertions(+) create mode 100644 tests/drivers/disk/disk_access/boards/native_posix_no_explicit_erase.overlay diff --git a/tests/drivers/disk/disk_access/boards/native_posix_no_explicit_erase.overlay b/tests/drivers/disk/disk_access/boards/native_posix_no_explicit_erase.overlay new file mode 100644 index 00000000000000..1d4edb73e972a9 --- /dev/null +++ b/tests/drivers/disk/disk_access/boards/native_posix_no_explicit_erase.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flashcontroller0 { + reg = <0x00000000 DT_SIZE_K(1024)>; +}; + +&flash0 { + reg = <0x00000000 DT_SIZE_K(1024)>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + flashdisk_partition: partition@0 { + label = "flashdisk"; + reg = <0x00000000 0x00100000>; + }; + }; +}; + +/ { + test_disk: storage_disk { + compatible = "zephyr,flash-disk"; + partition = <&flashdisk_partition>; + disk-name = "NAND"; + cache-size = <512>; + }; +}; diff --git a/tests/drivers/disk/disk_access/testcase.yaml b/tests/drivers/disk/disk_access/testcase.yaml index 9fc566158bc282..94f25c00703d0e 100644 --- a/tests/drivers/disk/disk_access/testcase.yaml +++ b/tests/drivers/disk/disk_access/testcase.yaml @@ -36,3 +36,11 @@ tests: - native_sim drivers.disk.stm32_sdhc: filter: dt_compat_enabled("st,stm32-sdmmc") + drivers.disk.simulator.no_explicit_erase: + extra_args: DTC_OVERLAY_FILE=boards/native_posix_no_explicit_erase.overlay + extra_configs: + - CONFIG_DISK_DRIVER_FLASH=y + - CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: + - native_posix/native/64 + - native_posix From 0c10b20cc8d02869dcbb802d6e95a06b7b866b1f Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 8 Feb 2024 21:47:11 +0000 Subject: [PATCH 046/981] drivers: nrf_qspi_nor: Mark driver with FLASH_HAS_EXPLICIT_ERASE All QSPI connected NOR Flash devices require erase prior to write. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nordic_qspi_nor | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/flash/Kconfig.nordic_qspi_nor b/drivers/flash/Kconfig.nordic_qspi_nor index 4acce55856791e..82e1e197e37534 100644 --- a/drivers/flash/Kconfig.nordic_qspi_nor +++ b/drivers/flash/Kconfig.nordic_qspi_nor @@ -7,6 +7,7 @@ menuconfig NORDIC_QSPI_NOR depends on DT_HAS_NORDIC_QSPI_NOR_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select NRFX_QSPI select FLASH_JESD216 select PINCTRL From 5da7df4e7c8497ea3b0a0a56eacd8b3cf80a83aa Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:59:35 +0000 Subject: [PATCH 047/981] Bluetooth: Mesh: Switch erase to flash_area_flatten The flash_area_erase has been replaced with flash_area_flatten, allowing code to work with devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- subsys/bluetooth/mesh/blob_io_flash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/blob_io_flash.c b/subsys/bluetooth/mesh/blob_io_flash.c index b82a7d20f7f7e9..31abd117e3ce41 100644 --- a/subsys/bluetooth/mesh/blob_io_flash.c +++ b/subsys/bluetooth/mesh/blob_io_flash.c @@ -88,8 +88,8 @@ static int block_start(const struct bt_mesh_blob_io *io, erase_size = block->size; #endif - return flash_area_erase(flash->area, flash->offset + block->offset, - erase_size); + return flash_area_flatten(flash->area, flash->offset + block->offset, + erase_size); } static int rd_chunk(const struct bt_mesh_blob_io *io, From def4f060c1f7ac4d837101e8cbfad6a34808b910 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 23:09:09 +0000 Subject: [PATCH 048/981] storage/settings: Replace flash_area_erase with flash_area_flatten Replace flash_area_erase with flash_area_flatten to allow FCB Settings backend to work on devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- subsys/settings/src/settings_fcb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/settings/src/settings_fcb.c b/subsys/settings/src/settings_fcb.c index 3922c54fb0880a..f58e4e3700b3e7 100644 --- a/subsys/settings/src/settings_fcb.c +++ b/subsys/settings/src/settings_fcb.c @@ -74,7 +74,7 @@ int settings_fcb_src(struct settings_fcb *cf) */ if (fcb_free_sector_cnt(&cf->cf_fcb) < 1) { - rc = flash_area_erase(cf->cf_fcb.fap, + rc = flash_area_flatten(cf->cf_fcb.fap, cf->cf_fcb.f_active.fe_sector->fs_off, cf->cf_fcb.f_active.fe_sector->fs_size); @@ -424,7 +424,7 @@ int settings_backend_init(void) return rc; } - rc = flash_area_erase(fap, 0, fap->fa_size); + rc = flash_area_flatten(fap, 0, fap->fa_size); flash_area_close(fap); if (rc != 0) { From 743d66a7e5d10b2fea4d836f651f385a1962fee3 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 23:10:58 +0000 Subject: [PATCH 049/981] debug/coredump/flash_backend: Switch to flash_area_flatten Replace usage of flash_area_erase with flash_area_flatten to allow code to work with devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- .../coredump_backend_flash_partition.c | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/subsys/debug/coredump/coredump_backend_flash_partition.c b/subsys/debug/coredump/coredump_backend_flash_partition.c index 434cd4774a1803..6f96ae726d2201 100644 --- a/subsys/debug/coredump/coredump_backend_flash_partition.c +++ b/subsys/debug/coredump/coredump_backend_flash_partition.c @@ -39,12 +39,21 @@ LOG_MODULE_REGISTER(coredump, CONFIG_KERNEL_LOG_LEVEL); #else +/* Note that currently external memories are not supported */ #define FLASH_CONTROLLER \ DT_PARENT(DT_PARENT(DT_NODELABEL(FLASH_PARTITION))) #define FLASH_WRITE_SIZE DT_PROP(FLASH_CONTROLLER, write_block_size) #define FLASH_BUF_SIZE FLASH_WRITE_SIZE -#define FLASH_ERASE_SIZE DT_PROP(FLASH_CONTROLLER, erase_block_size) +#if DT_NODE_HAS_PROP(FLASH_CONTROLLER, erase_block_size) +#define DEVICE_ERASE_BLOCK_SIZE DT_PROP(FLASH_CONTROLLER, erase_block_size) +#else +/* Device has no erase block size */ +#define DEVICE_ERASE_BLOCK_SIZE 1 +#endif + +#define HEADER_SCRAMBLE_SIZE ROUND_UP(sizeof(struct flash_hdr_t), \ + DEVICE_ERASE_BLOCK_SIZE) #define HDR_VER 1 @@ -344,9 +353,9 @@ static int get_stored_dump(off_t off, uint8_t *dst, size_t len) } /** - * @brief Erase the stored coredump header from flash partition. + * @brief Erase or scramble the stored coredump header from flash partition. * - * This erases the stored coredump header from the flash partition, + * This erases or scrambles the stored coredump header from the flash partition, * invalidating the coredump data. * * @return 0 if successful; error otherwise @@ -357,10 +366,9 @@ static int erase_coredump_header(void) ret = partition_open(); if (ret == 0) { - /* Erase header block */ - ret = flash_area_erase(backend_ctx.flash_area, 0, - ROUND_UP(sizeof(struct flash_hdr_t), - FLASH_ERASE_SIZE)); + /* Erase or scramble header block */ + ret = flash_area_flatten(backend_ctx.flash_area, 0, + HEADER_SCRAMBLE_SIZE); } partition_close(); @@ -382,8 +390,8 @@ static int erase_flash_partition(void) ret = partition_open(); if (ret == 0) { /* Erase whole flash partition */ - ret = flash_area_erase(backend_ctx.flash_area, 0, - backend_ctx.flash_area->fa_size); + ret = flash_area_flatten(backend_ctx.flash_area, 0, + backend_ctx.flash_area->fa_size); } partition_close(); @@ -406,8 +414,8 @@ static void coredump_flash_backend_start(void) if (ret == 0) { /* Erase whole flash partition */ - ret = flash_area_erase(backend_ctx.flash_area, 0, - backend_ctx.flash_area->fa_size); + ret = flash_area_flatten(backend_ctx.flash_area, 0, + backend_ctx.flash_area->fa_size); } if (ret == 0) { From 9da26eda5eafa4d988660d00209fee616eb1629d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 23:06:57 +0000 Subject: [PATCH 050/981] fs/littlefs: Use flash_area_flatten in lfs_api_erase LittleFS is based on program-erase devices and require that characteristics to work; the commit replaces flash_area_erase with flash_area_flatten to allow LFS work on devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- subsys/fs/Kconfig.littlefs | 2 +- subsys/fs/littlefs_fs.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/subsys/fs/Kconfig.littlefs b/subsys/fs/Kconfig.littlefs index 50ebf7531f7a09..c3ebde18c39659 100644 --- a/subsys/fs/Kconfig.littlefs +++ b/subsys/fs/Kconfig.littlefs @@ -106,7 +106,7 @@ endif # FS_LITTLEFS_FC_HEAP_SIZE <= 0 config FS_LITTLEFS_FMP_DEV bool "Support for littlefs on flash devices" depends on FLASH_MAP - depends on FLASH_PAGE_LAYOUT + depends on FLASH_PAGE_LAYOUT || !FLASH_HAS_EXPLICIT_ERASE default y help Enable this option to provide support for littlefs on flash devices diff --git a/subsys/fs/littlefs_fs.c b/subsys/fs/littlefs_fs.c index b373ca92ba8ead..5989f856ac1f23 100644 --- a/subsys/fs/littlefs_fs.c +++ b/subsys/fs/littlefs_fs.c @@ -28,6 +28,9 @@ #include "fs_impl.h" +/* Used on devices that have no explicit erase */ +#define LITTLEFS_DEFAULT_BLOCK_SIZE 4096 + /* note: one of the next options have to be enabled, at least */ BUILD_ASSERT(IS_ENABLED(CONFIG_FS_LITTLEFS_BLK_DEV) || IS_ENABLED(CONFIG_FS_LITTLEFS_FMP_DEV)); @@ -195,7 +198,7 @@ static int lfs_api_erase(const struct lfs_config *c, lfs_block_t block) const struct flash_area *fa = c->context; size_t offset = block * c->block_size; - int rc = flash_area_erase(fa, offset, c->block_size); + int rc = flash_area_flatten(fa, offset, c->block_size); return errno_to_lfs(rc); } @@ -581,6 +584,7 @@ static int littlefs_statvfs(struct fs_mount_t *mountp, #ifdef CONFIG_FS_LITTLEFS_FMP_DEV +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) /* Return maximum page size in a flash area. There's no flash_area * API to implement this, so we have to make one here. */ @@ -612,6 +616,7 @@ static bool get_page_cb(const struct flash_pages_info *info, void *ctxp) return true; } +#endif /* Iterate over all page groups in the flash area and return the * largest page size we see. This works as long as the partition is @@ -620,15 +625,26 @@ static bool get_page_cb(const struct flash_pages_info *info, void *ctxp) */ static lfs_size_t get_block_size(const struct flash_area *fa) { +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) struct get_page_ctx ctx = { .area = fa, .max_size = 0, }; const struct device *dev = flash_area_get_device(fa); +#if defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + const struct flash_parameters *fparams = flash_get_parameters(dev); + + if (!(flash_params_get_erase_cap(fparams) & FLASH_ERASE_C_EXPLICIT)) { + return LITTLEFS_DEFAULT_BLOCK_SIZE; + } +#endif flash_page_foreach(dev, get_page_cb, &ctx); return ctx.max_size; +#else + return LITTLEFS_DEFAULT_BLOCK_SIZE; +#endif } static int littlefs_flash_init(struct fs_littlefs *fs, void *dev_id) From 64ccfb0479cade35e754c8dbe92b8cac169059df Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Mar 2024 19:28:31 +0000 Subject: [PATCH 051/981] fs/fcb: Replace flash_area_erase with flash_area_flatten FCB depends on explicit erase characteristics of a device. Signed-off-by: Dominik Ermel --- subsys/fs/fcb/fcb.c | 3 +-- tests/subsys/fs/fcb/testcase.yaml | 6 ++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/subsys/fs/fcb/fcb.c b/subsys/fs/fcb/fcb.c index 778df0f54a6f11..44358a8dbeac3e 100644 --- a/subsys/fs/fcb/fcb.c +++ b/subsys/fs/fcb/fcb.c @@ -82,8 +82,7 @@ fcb_erase_sector(const struct fcb *fcb, const struct flash_sector *sector) return -EIO; } - rc = flash_area_erase(fcb->fap, sector->fs_off, sector->fs_size); - + rc = flash_area_flatten(fcb->fap, sector->fs_off, sector->fs_size); if (rc != 0) { return -EIO; } diff --git a/tests/subsys/fs/fcb/testcase.yaml b/tests/subsys/fs/fcb/testcase.yaml index e01566b6721bb0..19e47e33a1bdc5 100644 --- a/tests/subsys/fs/fcb/testcase.yaml +++ b/tests/subsys/fs/fcb/testcase.yaml @@ -12,6 +12,12 @@ tests: tags: flash_circural_buffer integration_platforms: - nrf52840dk/nrf52840 + filesystem.fcb.no_erase: + platform_allow: + - nrf54l15pdk/nrf54l15/cpuapp + filesystem.fcb.native_sim.no_erase: + extra_args: CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: native_sim filesystem.fcb.native_sim.fcb_0x00: extra_args: DTC_OVERLAY_FILE=boards/native_sim_ev_0x00.overlay platform_allow: native_sim From bf7d25117a65b5a7cab02c6191319c3d305e6874 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 8 Feb 2024 22:31:37 +0000 Subject: [PATCH 052/981] fs/nvs: Switch to use flash_flatten instead of flash_erase The NVS currently requires explict erase capability of a device to work, so usage of flash_erase has been replaced with flash_flatten. There has been additional LOG_WRN added to warn user that NVS may not efficiently work with device that do not really have erase. Currently NVS relies on devices that require erase. Signed-off-by: Dominik Ermel --- subsys/fs/nvs/nvs.c | 2 +- tests/subsys/fs/nvs/src/main.c | 11 +++++++++++ tests/subsys/fs/nvs/testcase.yaml | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/subsys/fs/nvs/nvs.c b/subsys/fs/nvs/nvs.c index ef35e677710e9b..a07f9b3198bb11 100644 --- a/subsys/fs/nvs/nvs.c +++ b/subsys/fs/nvs/nvs.c @@ -308,7 +308,7 @@ static int nvs_flash_erase_sector(struct nvs_fs *fs, uint32_t addr) #ifdef CONFIG_NVS_LOOKUP_CACHE nvs_lookup_cache_invalidate(fs, addr >> ADDR_SECT_SHIFT); #endif - rc = flash_erase(fs->flash_device, offset, fs->sector_size); + rc = flash_flatten(fs->flash_device, offset, fs->sector_size); if (rc) { return rc; diff --git a/tests/subsys/fs/nvs/src/main.c b/tests/subsys/fs/nvs/src/main.c index 97e41f15b96664..34a0080866d95a 100644 --- a/tests/subsys/fs/nvs/src/main.c +++ b/tests/subsys/fs/nvs/src/main.c @@ -207,7 +207,18 @@ ZTEST_F(nvs, test_nvs_corrupted_write) &flash_max_write_calls); stats_walk(fixture->sim_stats, flash_sim_write_calls_find, &flash_write_stat); +#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) *flash_max_write_calls = *flash_write_stat - 1; +#else + /* When there is no explicit erase, erase is done with write, which means + * that there are more writes needed. The nvs_write here will cause erase + * to be called, which in turn calls the flash_fill; flash_fill will + * overwrite data using buffer of size CONFIG_FLASH_FILL_BUFFER_SIZE, + * and then two additional real writes are allowed. + */ + *flash_max_write_calls = (fixture->fs.sector_size / + CONFIG_FLASH_FILL_BUFFER_SIZE) + 2; +#endif *flash_write_stat = 0; /* Flash simulator will lose part of the data at the end of this write. diff --git a/tests/subsys/fs/nvs/testcase.yaml b/tests/subsys/fs/nvs/testcase.yaml index f462a33ff0ed52..f02fc257fc1d3c 100644 --- a/tests/subsys/fs/nvs/testcase.yaml +++ b/tests/subsys/fs/nvs/testcase.yaml @@ -6,6 +6,9 @@ tests: filesystem.nvs.0x00: extra_args: DTC_OVERLAY_FILE=boards/qemu_x86_ev_0x00.overlay platform_allow: qemu_x86 + filesystem.nvs.sim.no_erase: + extra_args: CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: qemu_x86 filesystem.nvs.cache: extra_args: - CONFIG_NVS_LOOKUP_CACHE=y From 1ae352a760e1d7e2d1fca21c9ee185996459dce7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:24:46 +0000 Subject: [PATCH 053/981] tests/fs: Replace flash_area_erase with flash_area_flatten Test of file systems use flash_area_erase to erase device to have a clear start for tests; switching to flash_area_flatten allows them to do the same with devices that do not explicit call to erase procedure before write. Signed-off-by: Dominik Ermel --- tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c | 2 +- tests/subsys/fs/fcb/src/main.c | 2 +- tests/subsys/fs/littlefs/src/testfs_lfs.c | 2 +- tests/subsys/fs/multi-fs/src/test_utils.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c b/tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c index a377fd1a5234a0..5af5b53788cbbe 100644 --- a/tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c +++ b/tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c @@ -45,7 +45,7 @@ static int wipe_partition(void) } TC_PRINT("Erasing %zu (0x%zx) bytes\n", pfa->fa_size, pfa->fa_size); - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); (void)flash_area_close(pfa); if (rc < 0) { diff --git a/tests/subsys/fs/fcb/src/main.c b/tests/subsys/fs/fcb/src/main.c index fb2afd6dc9f4ac..2603f7fddf586e 100644 --- a/tests/subsys/fs/fcb/src/main.c +++ b/tests/subsys/fs/fcb/src/main.c @@ -58,7 +58,7 @@ void test_fcb_wipe(void) zassert_true(rc == 0, "flash area open call failure"); for (i = 0; i < ARRAY_SIZE(test_fcb_sector); i++) { - rc = flash_area_erase(fap, test_fcb_sector[i].fs_off, + rc = flash_area_flatten(fap, test_fcb_sector[i].fs_off, test_fcb_sector[i].fs_size); zassert_true(rc == 0, "erase call failure"); } diff --git a/tests/subsys/fs/littlefs/src/testfs_lfs.c b/tests/subsys/fs/littlefs/src/testfs_lfs.c index c195b7cde0b671..01737749ec1811 100644 --- a/tests/subsys/fs/littlefs/src/testfs_lfs.c +++ b/tests/subsys/fs/littlefs/src/testfs_lfs.c @@ -73,7 +73,7 @@ int testfs_lfs_wipe_partition(const struct fs_mount_t *mp) } TC_PRINT("Erasing %zu (0x%zx) bytes\n", pfa->fa_size, pfa->fa_size); - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); (void)flash_area_close(pfa); if (rc < 0) { diff --git a/tests/subsys/fs/multi-fs/src/test_utils.c b/tests/subsys/fs/multi-fs/src/test_utils.c index 1f50240df0690b..579007ab8ff2ab 100644 --- a/tests/subsys/fs/multi-fs/src/test_utils.c +++ b/tests/subsys/fs/multi-fs/src/test_utils.c @@ -31,6 +31,6 @@ void test_clear_flash(void) rc = flash_area_open(TEST_PARTITION_ID, &fap); zassert_equal(rc, 0, "Opening flash area for erase [%d]\n", rc); - rc = flash_area_erase(fap, 0, fap->fa_size); + rc = flash_area_flatten(fap, 0, fap->fa_size); zassert_equal(rc, 0, "Erasing flash area [%d]\n", rc); } From 7894474cf9a2644682428d4f360c5ea8e71ad4cb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:21:20 +0000 Subject: [PATCH 054/981] tests/settings: Move from flash_area_erase to flash_area_flatten The Settings test wipe out areas to have a start clean, so flash_arae_flatten will do that form them for program-erase and no-erase devices. Signed-off-by: Dominik Ermel --- tests/subsys/settings/fcb/src/settings_test_fcb.c | 2 +- tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c | 2 +- tests/subsys/settings/file/src/settings_setup_littlefs.c | 2 +- tests/subsys/settings/functional/src/settings_basic_test.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/subsys/settings/fcb/src/settings_test_fcb.c b/tests/subsys/settings/fcb/src/settings_test_fcb.c index fdc2b7b8aac804..1b3097c6f8b31a 100644 --- a/tests/subsys/settings/fcb/src/settings_test_fcb.c +++ b/tests/subsys/settings/fcb/src/settings_test_fcb.c @@ -193,7 +193,7 @@ void config_wipe_fcb(struct flash_sector *fs, int cnt) rc = flash_area_open(TEST_PARTITION_ID, &fap); for (i = 0; i < cnt; i++) { - rc = flash_area_erase(fap, fs[i].fs_off, fs[i].fs_size); + rc = flash_area_flatten(fap, fs[i].fs_off, fs[i].fs_size); zassert_true(rc == 0, "Can't get flash area"); } } diff --git a/tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c b/tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c index 964fc87c166585..8e3be17c4b3544 100644 --- a/tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c +++ b/tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c @@ -110,7 +110,7 @@ void test_prepare_storage(void) err = flash_area_open(TEST_PARTITION_ID, &fa); zassert_true(err == 0, "Can't open storage flash area"); - err = flash_area_erase(fa, 0, fa->fa_size); + err = flash_area_flatten(fa, 0, fa->fa_size); zassert_true(err == 0, "Can't erase storage flash area"); err = flash_area_open(CODE_PARTITION_ID, &fa); diff --git a/tests/subsys/settings/file/src/settings_setup_littlefs.c b/tests/subsys/settings/file/src/settings_setup_littlefs.c index 2e2beb8bcee093..5e1705b876bfd3 100644 --- a/tests/subsys/settings/file/src/settings_setup_littlefs.c +++ b/tests/subsys/settings/file/src/settings_setup_littlefs.c @@ -29,7 +29,7 @@ void *config_setup_fs(void) rc = flash_area_open(LITTLEFS_PARTITION_ID, &fap); zassume_true(rc == 0, "opening flash area for erase [%d]\n", rc); - rc = flash_area_erase(fap, 0, fap->fa_size); + rc = flash_area_flatten(fap, 0, fap->fa_size); zassume_true(rc == 0, "erasing flash area [%d]\n", rc); rc = fs_mount(&littlefs_mnt); diff --git a/tests/subsys/settings/functional/src/settings_basic_test.c b/tests/subsys/settings/functional/src/settings_basic_test.c index 81d4934fbfa1f6..5798605a5a709e 100644 --- a/tests/subsys/settings/functional/src/settings_basic_test.c +++ b/tests/subsys/settings/functional/src/settings_basic_test.c @@ -45,7 +45,7 @@ ZTEST(settings_functional, test_clear_settings) rc = flash_area_open(TEST_FLASH_AREA_ID, &fap); if (rc == 0) { - rc = flash_area_erase(fap, 0, fap->fa_size); + rc = flash_area_flatten(fap, 0, fap->fa_size); flash_area_close(fap); } zassert_true(rc == 0, "clear settings failed"); From 95dfd1210d0fe2e5aa1a8cfd5a681860cf04a2fb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Mar 2024 20:49:48 +0000 Subject: [PATCH 055/981] storage/stream_flash: Support for devices without explicit erase Support for devices not requiring erase with Stream Flash API. Signed-off-by: Dominik Ermel --- subsys/storage/stream/Kconfig | 2 ++ subsys/storage/stream/stream_flash.c | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/subsys/storage/stream/Kconfig b/subsys/storage/stream/Kconfig index 63a9df458513f3..59a985feb12488 100644 --- a/subsys/storage/stream/Kconfig +++ b/subsys/storage/stream/Kconfig @@ -11,8 +11,10 @@ menuconfig STREAM_FLASH Enable support of stream to flash API if STREAM_FLASH + config STREAM_FLASH_ERASE bool "Perform erase operations" + depends on FLASH_HAS_EXPLICIT_ERASE help If disabled an external actor must erase the flash area being written to. diff --git a/subsys/storage/stream/stream_flash.c b/subsys/storage/stream/stream_flash.c index e9b1a3dbc27225..b9bd63df411bed 100644 --- a/subsys/storage/stream/stream_flash.c +++ b/subsys/storage/stream/stream_flash.c @@ -76,9 +76,18 @@ static int settings_direct_loader(const char *key, size_t len, int stream_flash_erase_page(struct stream_flash_ctx *ctx, off_t off) { +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) int rc; struct flash_pages_info page; +#if IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + /* There are both types of devices */ + const struct flash_parameters *fparams = flash_get_parameters(ctx->fdev); + /* Stream flash does not rely on erase, it does it when device needs it */ + if (!(flash_params_get_erase_cap(fparams) & FLASH_ERASE_C_EXPLICIT)) { + return 0; + } +#endif rc = flash_get_page_info_by_offs(ctx->fdev, off, &page); if (rc != 0) { LOG_ERR("Error %d while getting page info", rc); @@ -100,6 +109,9 @@ int stream_flash_erase_page(struct stream_flash_ctx *ctx, off_t off) } return rc; +#else + return 0; +#endif } #endif /* CONFIG_STREAM_FLASH_ERASE */ From 27f5291b9461f2cc491530178608d68783b31be8 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Mar 2024 20:57:47 +0000 Subject: [PATCH 056/981] tests/storage/stream_flash: Support for devices without explicit erase Adds code that runs erase only when needed. Signed-off-by: Dominik Ermel --- .../storage/stream/stream_flash/src/main.c | 17 ++++++++++++++++- .../storage/stream/stream_flash/testcase.yaml | 13 +++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/subsys/storage/stream/stream_flash/src/main.c b/tests/subsys/storage/stream/stream_flash/src/main.c index 089f68cd72e499..7b4627101c236c 100644 --- a/tests/subsys/storage/stream/stream_flash/src/main.c +++ b/tests/subsys/storage/stream/stream_flash/src/main.c @@ -41,7 +41,9 @@ static uint8_t generic_buf[BUF_LEN]; static uint8_t read_buf[TESTBUF_SIZE]; const static uint8_t write_buf[TESTBUF_SIZE] = {[0 ... TESTBUF_SIZE - 1] = 0xaa}; static uint8_t written_pattern[TESTBUF_SIZE] = {[0 ... TESTBUF_SIZE - 1] = 0xaa}; +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) static uint8_t erased_pattern[TESTBUF_SIZE] = {[0 ... TESTBUF_SIZE - 1] = 0xff}; +#endif #define VERIFY_BUF(start, size, buf) \ do { \ @@ -51,7 +53,11 @@ do { \ } while (0) #define VERIFY_WRITTEN(start, size) VERIFY_BUF(start, size, written_pattern) +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) #define VERIFY_ERASED(start, size) VERIFY_BUF(start, size, erased_pattern) +#else +#define VERIFY_ERASED(start, size) +#endif int stream_flash_callback(uint8_t *buf, size_t len, size_t offset) { @@ -66,7 +72,15 @@ int stream_flash_callback(uint8_t *buf, size_t len, size_t offset) static void erase_flash(void) { +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) int rc; +#if IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + const struct flash_parameters *fparam = flash_get_parameters(fdev); + + if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) { + return; + } +#endif for (int i = 0; i < MAX_NUM_PAGES; i++) { rc = flash_erase(fdev, @@ -74,6 +88,7 @@ static void erase_flash(void) layout->pages_size); zassert_equal(rc, 0, "should succeed"); } +#endif } @@ -588,7 +603,7 @@ ZTEST(lib_stream_flash, test_stream_flash_progress_resume) bytes_written = load_progress(progress_key); zassert_equal(bytes_written, bytes_written_old, "expected bytes_written to be loaded"); -#ifdef CONFIG_STREAM_FLASH_ERASE +#if defined(CONFIG_STREAM_FLASH_ERASE) zassert_equal(erase_offset_old, ctx.last_erased_page_start_offset, "expected last erased page offset to be loaded"); #endif diff --git a/tests/subsys/storage/stream/stream_flash/testcase.yaml b/tests/subsys/storage/stream/stream_flash/testcase.yaml index a2df663d8714fb..5d4e35a6ead4cc 100644 --- a/tests/subsys/storage/stream/stream_flash/testcase.yaml +++ b/tests/subsys/storage/stream/stream_flash/testcase.yaml @@ -9,6 +9,19 @@ common: tests: storage.stream_flash: tags: stream_flash + storage.stream_flash.simulator.no_explicit_erase: + extra_args: + - CONFIG_STREAM_FLASH_ERASE=n + - CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: + - native_posix + - native_posix/native/64 + - native_sim + - native_sim/native/64 + tags: stream_flash + storage.stream_flash.no_explicit_erase: + platform_allow: + - nrf54l15pdk/nrf54l15/cpuapp storage.stream_flash.dword_wbs: extra_args: DTC_OVERLAY_FILE=unaligned_flush.overlay tags: stream_flash From bce06a64c41451fa7b417d048e403632e44cc680 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:34:46 +0000 Subject: [PATCH 057/981] mgmt/mcumgr: Replace use of flash_area_erase with flash_area_flatten The commit replaces flash_area_erase with flash_area_flatten. The function is used in to places: 1) in image management commands IMG_MGMT_ID_UPLOAD and IMG_MGMT_ID_ERASE: to erase an image in secondary slot or to scramble trailer part of image, which could be misunderstood by MCUboot as valid image operation request; 2) in command ZEPHYR_MGMT_GRP_BASIC_CMD_ERASE_STORAGE to erase/scramble data partition. Signed-off-by: Dominik Ermel --- subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c | 6 +++--- subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c index c899e31a3fb9bd..b24babc6f8cbff 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c @@ -294,7 +294,7 @@ int img_mgmt_erase_slot(int slot) rc = img_mgmt_flash_check_empty_inner(fa); if (rc == 0) { - rc = flash_area_erase(fa, 0, fa->fa_size); + rc = flash_area_flatten(fa, 0, fa->fa_size); if (rc != 0) { LOG_ERR("Failed to erase flash area: %d", rc); @@ -473,7 +473,7 @@ int img_mgmt_erase_image_data(unsigned int off, unsigned int num_bytes) size_t erase_size = page.start_offset + page.size - fa->fa_off; - rc = flash_area_erase(fa, 0, erase_size); + rc = flash_area_flatten(fa, 0, erase_size); if (rc != 0) { LOG_ERR("image slot erase of 0x%zx bytes failed (err %d)", erase_size, @@ -498,7 +498,7 @@ int img_mgmt_erase_image_data(unsigned int off, unsigned int num_bytes) off = page.start_offset - fa->fa_off; erase_size = fa->fa_size - off; - rc = flash_area_erase(fa, off, erase_size); + rc = flash_area_flatten(fa, off, erase_size); if (rc != 0) { LOG_ERR("image slot trailer erase of 0x%zx bytes failed (err %d)", erase_size, rc); diff --git a/subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c b/subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c index 633b840a1a401d..7c7c5d50161f55 100644 --- a/subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c @@ -31,7 +31,7 @@ static int storage_erase(void) LOG_ERR("Failed to get flash area device"); rc = ZEPHYRBASIC_MGMT_ERR_FLASH_CONFIG_QUERY_FAIL; } else { - rc = flash_area_erase(fa, 0, fa->fa_size); + rc = flash_area_flatten(fa, 0, fa->fa_size); if (rc < 0) { LOG_ERR("Failed to erase flash area"); From c4c7e15ba10fad75e13e95ce5d105e53e1d6ce12 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:49:32 +0000 Subject: [PATCH 058/981] dfu/mcuboot: Use flash_area_flatten instead of flash_area_erase The invocation of flash_area_erase, in boot_erase_img_bank, has been replaced by flash_area_flatten. Signed-off-by: Dominik Ermel --- subsys/dfu/boot/mcuboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/dfu/boot/mcuboot.c b/subsys/dfu/boot/mcuboot.c index 4f03c7c9e24c9f..20015349dbc6e1 100644 --- a/subsys/dfu/boot/mcuboot.c +++ b/subsys/dfu/boot/mcuboot.c @@ -252,7 +252,7 @@ int boot_erase_img_bank(uint8_t area_id) return rc; } - rc = flash_area_erase(fa, 0, fa->fa_size); + rc = flash_area_flatten(fa, 0, fa->fa_size); flash_area_close(fa); From 7b36d34504018d08ff5e812175fa7f952cc059eb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:46:00 +0000 Subject: [PATCH 059/981] tests/dfu: Replace flash_area_erase with flash_area_flatten Use flash_area_flatten instead of flash_area_erase; this allows to run tests on devices that do not require explicit erase before write or do not provide the callback. Signed-off-by: Dominik Ermel --- tests/subsys/dfu/img_util/src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/subsys/dfu/img_util/src/main.c b/tests/subsys/dfu/img_util/src/main.c index 8e518388bf353a..d72efa2cb06234 100644 --- a/tests/subsys/dfu/img_util/src/main.c +++ b/tests/subsys/dfu/img_util/src/main.c @@ -73,7 +73,7 @@ ZTEST(img_util, test_collecting) sizeof(erase_buf)); zassert_true(ret == 0, "Flash write failure (%d)", ret); #else - ret = flash_area_erase(ctx.flash_area, 0, ctx.flash_area->fa_size); + ret = flash_area_flatten(ctx.flash_area, 0, ctx.flash_area->fa_size); zassert_true(ret == 0, "Flash erase failure (%d)", ret); #endif @@ -137,7 +137,7 @@ ZTEST(img_util, test_check_flash) ret = flash_img_init_id(&ctx, SLOT1_PARTITION_ID); zassert_true(ret == 0, "Flash img init 1"); - ret = flash_area_erase(ctx.flash_area, 0, ctx.flash_area->fa_size); + ret = flash_area_flatten(ctx.flash_area, 0, ctx.flash_area->fa_size); zassert_true(ret == 0, "Flash erase failure (%d)\n", ret); ret = flash_img_buffered_write(&ctx, tst_vec, sizeof(tst_vec), true); zassert_true(ret == 0, "Flash img buffered write\n"); From 8dc1fcec03da35d078e3bbd7d06ff5794589bd18 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:44:28 +0000 Subject: [PATCH 060/981] tests: Bluetooth: Mesh: Use flash_area_flatten for erase The flash_area_erase is replaced with flash_area_flatten that is also able to erase/scramble devices that do not require explicit call to erase procedure before write. Signed-off-by: Dominik Ermel --- tests/bluetooth/mesh/blob_io_flash/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bluetooth/mesh/blob_io_flash/src/main.c b/tests/bluetooth/mesh/blob_io_flash/src/main.c index 18111e1565f797..62fe590e6d9144 100644 --- a/tests/bluetooth/mesh/blob_io_flash/src/main.c +++ b/tests/bluetooth/mesh/blob_io_flash/src/main.c @@ -68,7 +68,7 @@ ZTEST(blob_io_flash, test_chunk_read) err = flash_area_open(SLOT1_PARTITION_ID, &fa); zassert_equal(err, 0, "Preparing test data failed with err=%d", err); - err = flash_area_erase(fa, 0, ARRAY_SIZE(ctrl_data)); + err = flash_area_flatten(fa, 0, ARRAY_SIZE(ctrl_data)); zassert_equal(err, 0, "Preparing test data failed with err=%d", err); err = flash_area_write(fa, 0, test_data, ARRAY_SIZE(ctrl_data)); From c7037532b898a7143b966eee99979e57a8133c6d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 5 Feb 2024 15:56:16 +0000 Subject: [PATCH 061/981] samples/soc_flash_nrf: Adjust for non-Flash SoC devices The sample has been modified to work with devices that have no explicit erase capability. For that purpose printf messages have been modified to use "Internal storage" rather than "Flash" when reporting status. Signed-off-by: Dominik Ermel --- samples/drivers/soc_flash_nrf/README.rst | 23 +++--- samples/drivers/soc_flash_nrf/src/main.c | 95 ++++++++++++++++-------- 2 files changed, 74 insertions(+), 44 deletions(-) diff --git a/samples/drivers/soc_flash_nrf/README.rst b/samples/drivers/soc_flash_nrf/README.rst index 2b69d8d6cb6390..9f34ee631b6e98 100644 --- a/samples/drivers/soc_flash_nrf/README.rst +++ b/samples/drivers/soc_flash_nrf/README.rst @@ -1,5 +1,5 @@ .. zephyr:code-sample:: soc-flash-nrf - :name: nRF SoC flash + :name: nRF SoC Internal Storage :relevant-api: flash_interface flash_area_api Use the flash API to interact with the SoC flash. @@ -7,10 +7,11 @@ Overview ******** -This sample demonstrates using the :ref:`Flash API ` on an SoC internal flash. -The sample uses :ref:`Flash map API ` to obtain device for flash, using -DTS node label, and then directly uses :ref:`Flash API ` to perform -flash operations. +This sample demonstrates using the :ref:`Flash API ` on an SoC internal storage. +The sample uses :ref:`Flash map API ` to obtain a device that has +partition defined with label `storage_partition`, then uses :ref:`Flash API ` +to directly access and modify contents of a device, within area defined for said +partition. Within the sample, user may observe how read/write/erase operations are performed on a device, and how to first check whether device is @@ -19,11 +20,9 @@ ready for operation. Building and Running ******************** -The application will build for any SoC with internal flash memory -access enabled, as it is default for SoC devices, and fixed-partition -defined over that internal flash labeled `slot1_partition`, when -:kconfig:option:`CONFIG_TRUSTED_EXECUTION_NONSECURE` is not selected, -or `slot1_ns_partition`, when the Kconfig option is selected. +The application will build for any SoC with internal storage +access enabled, as it is default for SoC devices with defined +fixed-partition, over that internal storage, labeled `storage_partition`. .. zephyr-app-commands:: :zephyr-app: samples/drivers/soc_flash_nrf @@ -38,8 +37,8 @@ Sample Output *** Booting Zephyr OS build v2.7.99-17621-g54832687bcbb *** - Nordic nRF5 Flash Testing - ========================= + Nordic nRF5 Internal Storage Sample + =================================== Test 1: Flash erase page at 0x82000 Flash erase succeeded! diff --git a/samples/drivers/soc_flash_nrf/src/main.c b/samples/drivers/soc_flash_nrf/src/main.c index 29606a9ca5dfeb..d55214afcc515c 100644 --- a/samples/drivers/soc_flash_nrf/src/main.c +++ b/samples/drivers/soc_flash_nrf/src/main.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 Linaro Limited * 2016 Intel Corporation. + * Copyright (c) 2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,9 +28,45 @@ #define FLASH_TEST_OFFSET2 0x41234 #define FLASH_TEST_PAGE_IDX 37 +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && \ + IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) +#define FLASH_PE_RUNTIME_CHECK(cond) (cond) +#elif IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) +#define FLASH_PE_RUNTIME_CHECK(cond) (true) +#else +/* Assumed IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) */ +#define FLASH_PE_RUNTIME_CHECK(cond) (false) +#endif + +/** + * Depending on value of condition erase a device or not. The condition + * is supposed to be value of erase_requirement picked up from + * flash_parameters.flags for device. + */ +static void erase_when_needed(const struct device *dev, bool condition, + uint32_t off, uint32_t size) +{ + /* + * Alwayes invoke erase when there are only erase requiring devices, + * never invoke erase when there are no devices requiring erase, + * always check condition if there are both kind of devices. + */ + if (FLASH_PE_RUNTIME_CHECK(condition)) { + if (flash_erase(dev, off, size) != 0) { + printf(" Erase failed!\n"); + } else { + printf(" Erase succeeded!\n"); + } + } else { + (void)condition; + printf(" Erase not required by device\n"); + } +} + int main(void) { const struct device *flash_dev = TEST_PARTITION_DEVICE; + struct flash_parameters flash_params; uint32_t buf_array_1[4] = { TEST_DATA_WORD_0, TEST_DATA_WORD_1, TEST_DATA_WORD_2, TEST_DATA_WORD_3 }; uint32_t buf_array_2[4] = { TEST_DATA_WORD_3, TEST_DATA_WORD_1, @@ -41,35 +78,35 @@ int main(void) uint32_t buf_word = 0U; uint32_t i, offset; - printf("\nNordic nRF5 Flash Testing\n"); - printf("=========================\n"); + memcpy(&flash_params, flash_get_parameters(flash_dev), sizeof(flash_params)); + + printf("\nNordic nRF5 Internal Storage Sample\n"); + printf("=====================================\n"); if (!device_is_ready(flash_dev)) { - printf("Flash device not ready\n"); + printf("Internal storage device not ready\n"); return 0; } - printf("\nTest 1: Flash erase page at 0x%x\n", TEST_PARTITION_OFFSET); - if (flash_erase(flash_dev, TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE) != 0) { - printf(" Flash erase failed!\n"); - } else { - printf(" Flash erase succeeded!\n"); - } + printf("\nTest 1: Internal storage erase page at 0x%x\n", TEST_PARTITION_OFFSET); + erase_when_needed(flash_dev, + flash_params_get_erase_cap(&flash_params) & FLASH_ERASE_C_EXPLICIT, + TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE); - printf("\nTest 2: Flash write (word array 1)\n"); + printf("\nTest 2: Internal storage write (word array 1)\n"); for (i = 0U; i < ARRAY_SIZE(buf_array_1); i++) { offset = TEST_PARTITION_OFFSET + (i << 2); printf(" Attempted to write %x at 0x%x\n", buf_array_1[i], offset); if (flash_write(flash_dev, offset, &buf_array_1[i], sizeof(uint32_t)) != 0) { - printf(" Flash write failed!\n"); + printf(" Write failed!\n"); return 0; } printf(" Attempted to read 0x%x\n", offset); if (flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0) { - printf(" Flash read failed!\n"); + printf(" Read failed!\n"); return 0; } printf(" Data read: %x\n", buf_word); @@ -81,27 +118,24 @@ int main(void) } offset = TEST_PARTITION_OFFSET; - printf("\nTest 3: Flash erase (2 pages at 0x%x)\n", offset); - if (flash_erase(flash_dev, offset, FLASH_PAGE_SIZE * 2) != 0) { - printf(" Flash erase failed!\n"); - } else { - printf(" Flash erase succeeded!\n"); - } - - printf("\nTest 4: Flash write (word array 2)\n"); + printf("\nTest 3: Internal storage erase (2 pages at 0x%x)\n", offset); + erase_when_needed(flash_dev, + flash_params_get_erase_cap(&flash_params) & FLASH_ERASE_C_EXPLICIT, + offset, FLASH_PAGE_SIZE * 2); + printf("\nTest 4: Internal storage write (word array 2)\n"); for (i = 0U; i < ARRAY_SIZE(buf_array_2); i++) { offset = TEST_PARTITION_OFFSET + (i << 2); printf(" Attempted to write %x at 0x%x\n", buf_array_2[i], offset); if (flash_write(flash_dev, offset, &buf_array_2[i], sizeof(uint32_t)) != 0) { - printf(" Flash write failed!\n"); + printf(" Write failed!\n"); return 0; } printf(" Attempted to read 0x%x\n", offset); if (flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0) { - printf(" Flash read failed!\n"); + printf(" Read failed!\n"); return 0; } printf(" Data read: %x\n", buf_word); @@ -112,12 +146,10 @@ int main(void) } } - printf("\nTest 5: Flash erase page at 0x%x\n", TEST_PARTITION_OFFSET); - if (flash_erase(flash_dev, TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE) != 0) { - printf(" Flash erase failed!\n"); - } else { - printf(" Flash erase succeeded!\n"); - } + printf("\nTest 5: Internal storage erase page at 0x%x\n", TEST_PARTITION_OFFSET); + erase_when_needed(flash_dev, + flash_params_get_erase_cap(&flash_params) & FLASH_ERASE_C_EXPLICIT, + TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE); printf("\nTest 6: Non-word aligned write (word array 3)\n"); for (i = 0U; i < ARRAY_SIZE(buf_array_3); i++) { @@ -126,13 +158,13 @@ int main(void) offset); if (flash_write(flash_dev, offset, &buf_array_3[i], sizeof(uint32_t)) != 0) { - printf(" Flash write failed!\n"); + printf(" Write failed!\n"); return 0; } printf(" Attempted to read 0x%x\n", offset); if (flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0) { - printf(" Flash read failed!\n"); + printf(" Read failed!\n"); return 0; } printf(" Data read: %x\n", buf_word); @@ -185,8 +217,7 @@ int main(void) #endif printf("\nTest 8: Write block size API\n"); - printf(" write-block-size = %u\n", - flash_get_write_block_size(flash_dev)); + printf(" write-block-size = %u\n", flash_params.write_block_size); printf("\nFinished!\n"); return 0; From e31b8c8edfa9ce7cd506ddcefb13feb50f198380 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:54:18 +0000 Subject: [PATCH 062/981] samples/fs/littlefs: Use flash_area_flatten to wipe storage The commit replaces flash_area_erase with flash_area_flatten, as it allows to emulate erase and scramble data stored on devices that do not require explicit erase before write or do not provide erase callback. Signed-off-by: Dominik Ermel --- samples/subsys/fs/littlefs/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/subsys/fs/littlefs/src/main.c b/samples/subsys/fs/littlefs/src/main.c index 35fe1d2b3057b2..7723023013eb7c 100644 --- a/samples/subsys/fs/littlefs/src/main.c +++ b/samples/subsys/fs/littlefs/src/main.c @@ -252,7 +252,7 @@ static int littlefs_flash_erase(unsigned int id) /* Optional wipe flash contents */ if (IS_ENABLED(CONFIG_APP_WIPE_STORAGE)) { - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); LOG_ERR("Erasing flash area ... %d", rc); } From 856d7709bbc5db04590a9a2639ad51d952c34b40 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:54:18 +0000 Subject: [PATCH 063/981] samples/usb/imass: Use flash_area_flatten to wipe storage The commit replaces flash_area_erase with flash_area_flatten, as it allows to emulate erase and scramble data stored on devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- samples/subsys/usb/mass/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/subsys/usb/mass/src/main.c b/samples/subsys/usb/mass/src/main.c index 51718a9dc85957..733f6f90ea86fb 100644 --- a/samples/subsys/usb/mass/src/main.c +++ b/samples/subsys/usb/mass/src/main.c @@ -89,7 +89,7 @@ static int setup_flash(struct fs_mount_t *mnt) if (rc < 0 && IS_ENABLED(CONFIG_APP_WIPE_STORAGE)) { printk("Erasing flash area ... "); - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); printk("%d\n", rc); } From 56142dcc73f93a87248344beaba4b5c2e540762f Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 30 Mar 2024 15:11:59 +0100 Subject: [PATCH 064/981] drivers: flash: Mark numaker series RMC as no_explicit_erase The device is based on ReRAM and does not require erase. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.numaker_rmc | 1 + drivers/flash/soc_flash_numaker_rmc.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/flash/Kconfig.numaker_rmc b/drivers/flash/Kconfig.numaker_rmc index ae149115255f73..72fd64c4d494d8 100644 --- a/drivers/flash/Kconfig.numaker_rmc +++ b/drivers/flash/Kconfig.numaker_rmc @@ -8,6 +8,7 @@ config SOC_FLASH_NUMAKER_RMC default y select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_NO_EXPLICIT_ERASE select HAS_NUMAKER_RMC depends on DT_HAS_NUVOTON_NUMAKER_RMC_ENABLED help diff --git a/drivers/flash/soc_flash_numaker_rmc.c b/drivers/flash/soc_flash_numaker_rmc.c index 7e7d81f348b8ce..4a6b4ff6b5f531 100644 --- a/drivers/flash/soc_flash_numaker_rmc.c +++ b/drivers/flash/soc_flash_numaker_rmc.c @@ -29,6 +29,9 @@ struct flash_numaker_data { static const struct flash_parameters flash_numaker_parameters = { .write_block_size = SOC_NV_FLASH_WRITE_BLOCK_SIZE, .erase_value = 0xff, + .caps = { + .no_explicit_erase = true, + }, }; /* Validate offset and length */ From 7e658607fc77c51379bd969dec5eb00174e3486e Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 30 Mar 2024 16:22:56 +0100 Subject: [PATCH 065/981] drivers: flash: shell: Add support for devices without erase Shell will now work with devices that do not implement erase callback. Signed-off-by: Dominik Ermel --- drivers/flash/flash_shell.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/flash/flash_shell.c b/drivers/flash/flash_shell.c index 015bbbe99158eb..c3825d49ba39e7 100644 --- a/drivers/flash/flash_shell.c +++ b/drivers/flash/flash_shell.c @@ -75,9 +75,10 @@ static int cmd_erase(const struct shell *sh, size_t argc, char *argv[]) { const struct device *flash_dev; uint32_t page_addr; - int result; + int result = -ENOTSUP; uint32_t size; +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) result = parse_helper(sh, &argc, &argv, &flash_dev, &page_addr); if (result) { return result; @@ -106,6 +107,7 @@ static int cmd_erase(const struct shell *sh, size_t argc, char *argv[]) } else { shell_print(sh, "Erase success."); } +#endif return result; } From 12fa2944c9da209040401482e993e5f54a0dcb36 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 15:21:35 +0200 Subject: [PATCH 066/981] sample/fs: Add nrf54l15pdk/nrf54l15/cpuapp to fs_sample Adds custom overlay and config allowing the sample to run on the nrf54l15pdk. Signed-off-by: Dominik Ermel --- .../boards/nrf54l15pdk_nrf54l15_cpuapp.conf | 12 +++++ .../nrf54l15pdk_nrf54l15_cpuapp.overlay | 45 +++++++++++++++++++ samples/subsys/fs/fs_sample/sample.yaml | 3 ++ 3 files changed, 60 insertions(+) create mode 100644 samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf create mode 100644 samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay diff --git a/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf new file mode 100644 index 00000000000000..949237fd4bafd8 --- /dev/null +++ b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf @@ -0,0 +1,12 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_DISK_DRIVERS=y +CONFIG_DISK_DRIVER_FLASH=y +# There may be no files on internal SoC flash, so this Kconfig +# options has ben enabled to create some if listing does not +# find in the first place. +CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES=y diff --git a/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000000..391afea75a4047 --- /dev/null +++ b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Because FAT FS needs at least 64kiB partition and default + * storage_partition is 36kiB for this board, we need to reorganize + * partitions to get at least 64KiB. + */ +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; +/delete-node/ &slot0_ns_partition; +/delete-node/ &slot1_ns_partition; +/delete-node/ &storage_partition; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot0_partition: parition@10000 { + reg = <0x00010000 DT_SIZE_K(300)>; + }; + slot1_partition: partition@5b000 { + reg = <0x0005b000 DT_SIZE_K(300)>; + }; + + storage_partition: partition@a6000 { + label = "storage"; + reg = <0x000a6000 DT_SIZE_K(128)>; + }; + }; +}; + +/ { + msc_disk0 { + status="okay"; + compatible = "zephyr,flash-disk"; + partition = <&storage_partition>; + disk-name = "SD"; + cache-size = <512>; + }; +}; diff --git a/samples/subsys/fs/fs_sample/sample.yaml b/samples/subsys/fs/fs_sample/sample.yaml index 55dc3d8677a088..8041ffb84c45e5 100644 --- a/samples/subsys/fs/fs_sample/sample.yaml +++ b/samples/subsys/fs/fs_sample/sample.yaml @@ -43,6 +43,9 @@ tests: extra_args: - OVERLAY_CONFIG=boards/nrf52840dk_nrf52840_ram_disk.conf - DTC_OVERLAY_FILE=boards/nrf52840dk_nrf52840_ram_disk_region.overlay + sample.filesystem.fat_fs.nrf54l15pdk: + build_only: true + platform_allow: nrf54l15pdk/nrf54l15/cpuapp sample.filesystem.fat_fs.nrf52840dk_nrf52840.qspi: build_only: true platform_allow: nrf52840dk/nrf52840 From 12bfefd0872f39f3ca7e8d0528a4e2ff4bd8168f Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 15:29:02 +0200 Subject: [PATCH 067/981] tests/flash/common: Add nrf54l15pdk to list of allowed platforms Allows running tests on nrf54l15pdk/nrf54l15/cpuapp. Signed-off-by: Dominik Ermel --- tests/drivers/flash/common/testcase.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/drivers/flash/common/testcase.yaml b/tests/drivers/flash/common/testcase.yaml index 5bfd4a209447e8..028383fb5f8fa8 100644 --- a/tests/drivers/flash/common/testcase.yaml +++ b/tests/drivers/flash/common/testcase.yaml @@ -35,6 +35,9 @@ tests: integration_platforms: - qemu_x86 - mimxrt1060_evk + drivers.flash.common.no_explicit_erase: + platform_allow: + - nrf54l15pdk/nrf54l15/cpuapp drivers.flash.common.tfm_ns: build_only: true filter: (CONFIG_FLASH_HAS_DRIVER_ENABLED and CONFIG_TRUSTED_EXECUTION_NONSECURE From 9ea5aee810f5c8c568b0b651893bf35f1b28ae77 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 15:30:39 +0200 Subject: [PATCH 068/981] tests/fs/littlefs: Allow tests to run on the nrf54l15pdk The commit adds nrf54l15pdk/nrf54l15/cpuapp to list of allowed platforms for default test configuration. Signed-off-by: Dominik Ermel --- .../nrf54l15pdk_nrf54l15_cpuapp.overlay | 22 +++++++++++++++++++ tests/subsys/fs/littlefs/testcase.yaml | 1 + 2 files changed, 23 insertions(+) create mode 100644 tests/subsys/fs/littlefs/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay diff --git a/tests/subsys/fs/littlefs/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/tests/subsys/fs/littlefs/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000000..292e98c96a0331 --- /dev/null +++ b/tests/subsys/fs/littlefs/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &slot0_ns_partition; +/delete-node/ &slot1_partition; +/delete-node/ &slot1_ns_partition; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + small_partition: partition@67000 { + label = "small"; + reg = <0x00067000 0x00010000>; + }; + }; +}; diff --git a/tests/subsys/fs/littlefs/testcase.yaml b/tests/subsys/fs/littlefs/testcase.yaml index b64ffa43d96293..e934ac5b9d8cbb 100644 --- a/tests/subsys/fs/littlefs/testcase.yaml +++ b/tests/subsys/fs/littlefs/testcase.yaml @@ -15,6 +15,7 @@ common: tests: filesystem.littlefs.default: timeout: 60 + platform_allow: nrf54l15pdk/nrf54l15/cpuapp filesystem.littlefs.custom: timeout: 180 extra_configs: From e3866a969071be59fd70e896cfb9970cc9c397f0 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 15:32:31 +0200 Subject: [PATCH 069/981] samples/fs/littlefs: Allow building for nrf54l15pdk The commit adds nrf54l15pdk/nrf54l15/cpuapp target platfomr. Signed-off-by: Dominik Ermel --- samples/subsys/fs/littlefs/sample.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/subsys/fs/littlefs/sample.yaml b/samples/subsys/fs/littlefs/sample.yaml index 4c53a55d59104e..67231c5cfbdffa 100644 --- a/samples/subsys/fs/littlefs/sample.yaml +++ b/samples/subsys/fs/littlefs/sample.yaml @@ -24,6 +24,7 @@ tests: - stm32f746g_disco - stm32h747i_disco/stm32h747xx/m7 - stm32h750b_dk + - nrf54l15pdk/nrf54l15/cpuapp integration_platforms: - nrf52840dk/nrf52840 sample.filesystem.littlefs.blk: From c56134ebff9be049885bd59a0b214c55e8b5335e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 4 Jun 2024 06:56:12 +0000 Subject: [PATCH 070/981] drivers: flash: flash_util: params may be unused The params variable may be unused depending on the Kconfig options enabled. Fixes: #73697 Signed-off-by: Henrik Brix Andersen --- drivers/flash/flash_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/flash/flash_util.c b/drivers/flash/flash_util.c index ee3b55798a56b3..cbaaa2049097cd 100644 --- a/drivers/flash/flash_util.c +++ b/drivers/flash/flash_util.c @@ -65,7 +65,7 @@ int z_impl_flash_flatten(const struct device *dev, off_t offset, size_t size) { const struct flash_driver_api *api = (const struct flash_driver_api *)dev->api; - const struct flash_parameters *params = api->get_parameters(dev); + __maybe_unused const struct flash_parameters *params = api->get_parameters(dev); #if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) if ((flash_params_get_erase_cap(params) & FLASH_ERASE_C_EXPLICIT) && From c9c9c9797ff1967468606c4b3e69d54ff36474ad Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Tue, 14 May 2024 12:47:12 +0200 Subject: [PATCH 071/981] samples: basic: blinky_pwm: add testing base on console output Extend automated testing on HW by veryfing console output. Signed-off-by: Piotr Kosycarz --- samples/basic/blinky_pwm/sample.yaml | 11 ++++++++++- samples/basic/blinky_pwm/src/main.c | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/samples/basic/blinky_pwm/sample.yaml b/samples/basic/blinky_pwm/sample.yaml index de2cb234933c2d..d2087f73347f39 100644 --- a/samples/basic/blinky_pwm/sample.yaml +++ b/samples/basic/blinky_pwm/sample.yaml @@ -7,4 +7,13 @@ tests: - drivers - pwm depends_on: pwm - harness: led + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "PWM-based blinky" + - "Calibrating for channel [0-9]+" + - "Done calibrating; maximum/minimum periods [0-9]+/[0-9]+ nsec" + - "Using period [0-9]+" + - "Using period [0-9]+" diff --git a/samples/basic/blinky_pwm/src/main.c b/samples/basic/blinky_pwm/src/main.c index de1f6409c6d293..6539c05d5ccae1 100644 --- a/samples/basic/blinky_pwm/src/main.c +++ b/samples/basic/blinky_pwm/src/main.c @@ -63,6 +63,7 @@ int main(void) printk("Error %d: failed to set pulse width\n", ret); return 0; } + printk("Using period %d\n", period); period = dir ? (period * 2U) : (period / 2U); if (period > max_period) { From 447bdea7ffa7bc63338c149760c4fa63d42ae50a Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 16 May 2024 15:53:40 +0200 Subject: [PATCH 072/981] drivers: entropy: stm32 entropy driver add semaphore protection Add a semaphore to protect the disable access to the RNG peripheral when the PM is going to suspend mode. The change does not affect other stm32 than CONFIG_SOC_SERIES_STM32WBX or CONFIG_STM32H7_DUAL_CORE Signed-off-by: Francois Ramu --- drivers/entropy/entropy_stm32.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/entropy/entropy_stm32.c b/drivers/entropy/entropy_stm32.c index a9cbda2abc7304..2b079da3b8bf97 100644 --- a/drivers/entropy/entropy_stm32.c +++ b/drivers/entropy/entropy_stm32.c @@ -112,6 +112,10 @@ static int entropy_stm32_suspend(void) RNG_TypeDef *rng = dev_data->rng; int res; +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + /* Prevent concurrent access with PM */ + z_stm32_hsem_lock(CFG_HW_RNG_SEMID, HSEM_LOCK_WAIT_FOREVER); +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ LL_RNG_Disable(rng); #ifdef CONFIG_SOC_SERIES_STM32WBAX @@ -136,6 +140,10 @@ static int entropy_stm32_suspend(void) res = clock_control_off(dev_data->clock, (clock_control_subsys_t)&dev_cfg->pclken[0]); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + z_stm32_hsem_unlock(CFG_HW_RNG_SEMID); +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ + return res; } @@ -710,7 +718,12 @@ static int entropy_stm32_rng_pm_action(const struct device *dev, switch (action) { case PM_DEVICE_ACTION_SUSPEND: - res = entropy_stm32_suspend(); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + /* Lock to Prevent concurrent access with PM */ + z_stm32_hsem_lock(CFG_HW_RNG_SEMID, HSEM_LOCK_WAIT_FOREVER); + /* Call release_rng instead of entropy_stm32_suspend to avoid double hsem_unlock */ +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ + release_rng(); break; case PM_DEVICE_ACTION_RESUME: if (IS_ENABLED(CONFIG_PM_S2RAM)) { @@ -724,7 +737,15 @@ static int entropy_stm32_rng_pm_action(const struct device *dev, entropy_stm32_rng_init(dev); } else if (!entropy_stm32_rng_data.filling_pools) { /* Resume RNG only if it was suspended during filling pool */ - entropy_stm32_suspend(); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + /* Lock to Prevent concurrent access with PM */ + z_stm32_hsem_lock(CFG_HW_RNG_SEMID, HSEM_LOCK_WAIT_FOREVER); + /* + * Call release_rng instead of entropy_stm32_suspend + * to avoid double hsem_unlock + */ +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ + release_rng(); } #endif /* health_test_config */ } else { From 709b2e44bfdd159577cb2e15d17bc10b5c8dc783 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 31 May 2024 10:54:48 +0200 Subject: [PATCH 073/981] llext: automatically merge sections by type This patch changes the way sections are mapped to memories. Instead of looking at the section name, each section in the ELF file is mapped to the llext_mem enum by looking at the section type and flags. This allows for a more generic mapping that works for both the ARM and Xtensa cases, and also allows for sections to be merged if they are contiguous and non-overlapping in the ELF file. This patch also fixes a number of corner cases, such as in the logging test where a section with read-only data was being ignored (not copied and not relinked). Signed-off-by: Luca Burelli --- include/zephyr/llext/elf.h | 1 + include/zephyr/llext/loader.h | 3 - subsys/llext/llext.c | 178 +++++++++++++++++++++++++--------- 3 files changed, 132 insertions(+), 50 deletions(-) diff --git a/include/zephyr/llext/elf.h b/include/zephyr/llext/elf.h index 7e8628b37d5b94..b39af854312dae 100644 --- a/include/zephyr/llext/elf.h +++ b/include/zephyr/llext/elf.h @@ -196,6 +196,7 @@ struct elf64_shdr { elf64_xword sh_entsize; }; +#define SHT_NULL 0x0 #define SHT_PROGBITS 0x1 #define SHT_SYMTAB 0x2 #define SHT_STRTAB 0x3 diff --git a/include/zephyr/llext/loader.h b/include/zephyr/llext/loader.h index b8477eb30039f3..7eb49d611bed30 100644 --- a/include/zephyr/llext/loader.h +++ b/include/zephyr/llext/loader.h @@ -68,9 +68,6 @@ struct llext_loader { */ void *(*peek)(struct llext_loader *ldr, size_t pos); - /** Total calculated .data size for relocatable extensions */ - size_t prog_data_size; - /** @cond ignore */ elf_ehdr_t hdr; elf_shdr_t sects[LLEXT_MEM_COUNT]; diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index a647ac3bc27b04..ca5513b741f6ba 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -186,11 +186,13 @@ static int llext_find_tables(struct llext_loader *ldr) return ret; } - LOG_DBG("section %d at %zx: name %d, type %d, flags %zx, addr %zx, size %zd", + LOG_DBG("section %d at %zx: name %d, type %d, flags %zx, " + "ofs %zx, addr %zx, size %zd", i, pos, shdr.sh_name, shdr.sh_type, (size_t)shdr.sh_flags, + (size_t)shdr.sh_offset, (size_t)shdr.sh_addr, (size_t)shdr.sh_size); @@ -240,14 +242,11 @@ static const char *llext_string(struct llext_loader *ldr, struct llext *ext, */ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) { - int i, ret; + int i, j, ret; size_t pos; - elf_shdr_t shdr, rodata = {.sh_addr = ~0}, - high_shdr = {.sh_offset = 0}, low_shdr = {.sh_offset = ~0}; + elf_shdr_t shdr; const char *name; - ldr->sects[LLEXT_MEM_RODATA].sh_size = 0; - for (i = 0, pos = ldr->hdr.e_shoff; i < ldr->hdr.e_shnum; i++, pos += ldr->hdr.e_shentsize) { @@ -261,62 +260,145 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) return ret; } - /* Identify the lowest and the highest data sections */ - if (!(shdr.sh_flags & SHF_EXECINSTR) && - shdr.sh_type == SHT_PROGBITS) { - if (shdr.sh_offset > high_shdr.sh_offset) { - high_shdr = shdr; - } - if (shdr.sh_offset < low_shdr.sh_offset) { - low_shdr = shdr; - } + if ((shdr.sh_type != SHT_PROGBITS && shdr.sh_type != SHT_NOBITS) || + !(shdr.sh_flags & SHF_ALLOC) || + shdr.sh_size == 0) { + continue; } name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); - LOG_DBG("section %d name %s", i, name); - + /* Identify the section type by its flags */ enum llext_mem mem_idx; - /* - * .rodata section is optional. If there isn't one, use the - * first read-only data section - */ - if (shdr.sh_addr && !(shdr.sh_flags & (SHF_WRITE | SHF_EXECINSTR)) && - shdr.sh_addr < rodata.sh_addr) { - rodata = shdr; - LOG_DBG("rodata: select %#zx name %s", (size_t)shdr.sh_addr, name); - } - - /* - * Keep in mind, that when using relocatable (partially linked) - * objects, ELF segments aren't created, so ldr->sect_map[] and - * ldr->sects[] don't contain all the sections - */ - if (strcmp(name, ".text") == 0) { - mem_idx = LLEXT_MEM_TEXT; - } else if (strcmp(name, ".data") == 0) { - mem_idx = LLEXT_MEM_DATA; - } else if (strcmp(name, ".rodata") == 0) { - mem_idx = LLEXT_MEM_RODATA; - } else if (strcmp(name, ".bss") == 0) { + switch (shdr.sh_type) { + case SHT_NOBITS: mem_idx = LLEXT_MEM_BSS; - } else if (strcmp(name, ".exported_sym") == 0) { - mem_idx = LLEXT_MEM_EXPORT; - } else { + break; + case SHT_PROGBITS: + if (shdr.sh_flags & SHF_EXECINSTR) { + mem_idx = LLEXT_MEM_TEXT; + } else if (shdr.sh_flags & SHF_WRITE) { + mem_idx = LLEXT_MEM_DATA; + } else { + mem_idx = LLEXT_MEM_RODATA; + } + break; + default: LOG_DBG("Not copied section %s", name); continue; } - ldr->sects[mem_idx] = shdr; + /* Special exception for .exported_sym */ + if (strcmp(name, ".exported_sym") == 0) { + mem_idx = LLEXT_MEM_EXPORT; + } + + LOG_DBG("section %d name %s maps to idx %d", i, name, mem_idx); + ldr->sect_map[i] = mem_idx; + elf_shdr_t *sect = ldr->sects + mem_idx; + + if (sect->sh_type == SHT_NULL) { + /* First section of this type, copy all info */ + *sect = shdr; + } else { + /* Make sure the sections are compatible before merging */ + if (shdr.sh_flags != sect->sh_flags) { + LOG_ERR("Unsupported section flags for %s (mem %d)", + name, mem_idx); + return -ENOEXEC; + } + + if (mem_idx == LLEXT_MEM_BSS) { + /* SHT_NOBITS sections cannot be merged properly: + * as they use no space in the file, the logic + * below does not work; they must be treated as + * independent entities. + */ + LOG_ERR("Multiple SHT_NOBITS sections are not supported"); + return -ENOEXEC; + } + + if (ldr->hdr.e_type == ET_DYN) { + /* In shared objects, sh_addr is the VMA. Before + * merging these sections, make sure the delta + * in VMAs matches that of file offsets. + */ + if (shdr.sh_addr - sect->sh_addr != + shdr.sh_offset - sect->sh_offset) { + LOG_ERR("Incompatible section addresses " + "for %s (mem %d)", name, mem_idx); + return -ENOEXEC; + } + } + + /* + * Extend the current section to include the new one + * (overlaps are detected later) + */ + size_t address = MIN(sect->sh_addr, shdr.sh_addr); + size_t bot_ofs = MIN(sect->sh_offset, shdr.sh_offset); + size_t top_ofs = MAX(sect->sh_offset + sect->sh_size, + shdr.sh_offset + shdr.sh_size); + + sect->sh_addr = address; + sect->sh_offset = bot_ofs; + sect->sh_size = top_ofs - bot_ofs; + } } - ldr->prog_data_size = high_shdr.sh_size + high_shdr.sh_offset - low_shdr.sh_offset; + /* + * Test that no computed range overlaps. This can happen if sections of + * different llext_mem type are interleaved in the ELF file or in VMAs. + */ + for (i = 0; i < LLEXT_MEM_COUNT; i++) { + for (j = i+1; j < LLEXT_MEM_COUNT; j++) { + elf_shdr_t *x = ldr->sects + i; + elf_shdr_t *y = ldr->sects + j; + + if (x->sh_type == SHT_NULL || x->sh_size == 0 || + y->sh_type == SHT_NULL || y->sh_size == 0) { + /* Skip empty sections */ + continue; + } + + if (ldr->hdr.e_type == ET_DYN) { + /* + * Test all merged VMA ranges for overlaps + */ + if ((x->sh_addr <= y->sh_addr && + x->sh_addr + x->sh_size > y->sh_addr) || + (y->sh_addr <= x->sh_addr && + y->sh_addr + y->sh_size > x->sh_addr)) { + LOG_ERR("VMA range %d (0x%zx +%zd) " + "overlaps with %d (0x%zx +%zd)", + i, (size_t)x->sh_addr, (size_t)x->sh_size, + j, (size_t)y->sh_addr, (size_t)y->sh_size); + return -ENOEXEC; + } + } + + /* + * Test file offsets. BSS sections store no + * data in the file and must not be included + * in checks to avoid false positives. + */ + if (i == LLEXT_MEM_BSS || j == LLEXT_MEM_BSS) { + continue; + } - /* No verbatim .rodata, use an automatically selected one */ - if (!ldr->sects[LLEXT_MEM_RODATA].sh_size) { - ldr->sects[LLEXT_MEM_RODATA] = rodata; + if ((x->sh_offset <= y->sh_offset && + x->sh_offset + x->sh_size > y->sh_offset) || + (y->sh_offset <= x->sh_offset && + y->sh_offset + y->sh_size > x->sh_offset)) { + LOG_ERR("ELF file range %d (0x%zx +%zd) " + "overlaps with %d (0x%zx +%zd)", + i, (size_t)x->sh_offset, (size_t)x->sh_size, + j, (size_t)y->sh_offset, (size_t)y->sh_size); + return -ENOEXEC; + } + } } return 0; @@ -352,6 +434,8 @@ static void llext_init_mem_part(struct llext *ext, enum llext_mem mem_idx, ext->mem_parts[mem_idx].size); } #endif + + LOG_DBG("mem idx %d: start 0x%zx, size %zd", mem_idx, (size_t)start, len); } static int llext_copy_section(struct llext_loader *ldr, struct llext *ext, From 06bb9f258a0a5921b9c16ad8291c9be9a80a6881 Mon Sep 17 00:00:00 2001 From: Jens Rehhoff Thomsen Date: Fri, 31 May 2024 11:09:27 +0200 Subject: [PATCH 074/981] Bluetooth: BAP: Shell: Add endpoint state info The bap list command now also shows the states of each endpoint. Fixes #70838 Signed-off-by: Jens Rehhoff Thomsen --- subsys/bluetooth/audio/shell/bap.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index b560ba3c714df0..e63b2d559d15de 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -1649,7 +1649,13 @@ static void conn_list_eps(struct bt_conn *conn, void *data) const struct bt_bap_ep *ep = snks[conn_index][i]; if (ep != NULL) { - shell_print(sh, " #%u: ep %p", i, ep); + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(ep, &ep_info); + if (err == 0) { + shell_print(sh, " #%u: ep %p (state: %d)", i, ep, ep_info.state); + } } } #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */ @@ -1661,7 +1667,13 @@ static void conn_list_eps(struct bt_conn *conn, void *data) const struct bt_bap_ep *ep = srcs[conn_index][i]; if (ep != NULL) { - shell_print(sh, " #%u: ep %p", i, ep); + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(ep, &ep_info); + if (err == 0) { + shell_print(sh, " #%u: ep %p (state: %d)", i, ep, ep_info.state); + } } } #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */ From ebadb11645bd3e65df08b0ed5d3ce83250dea440 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 20 May 2024 19:40:04 +0200 Subject: [PATCH 075/981] Bluetooth: Audio: Spring cleaning Adds, removes and modifies includes in all LE audio files. Fixes any found spelling mistakes as well. Fixes a few places where incorrect types were used. Signed-off-by: Emil Gydesen --- include/zephyr/bluetooth/audio/aics.h | 3 + include/zephyr/bluetooth/audio/audio.h | 19 ++++-- include/zephyr/bluetooth/audio/bap.h | 12 +++- .../zephyr/bluetooth/audio/bap_lc3_preset.h | 1 + include/zephyr/bluetooth/audio/cap.h | 10 ++- include/zephyr/bluetooth/audio/csip.h | 9 +++ .../zephyr/bluetooth/audio/gmap_lc3_preset.h | 2 + include/zephyr/bluetooth/audio/has.h | 6 +- include/zephyr/bluetooth/audio/mcc.h | 3 +- include/zephyr/bluetooth/audio/mcs.h | 1 + include/zephyr/bluetooth/audio/media_proxy.h | 1 + include/zephyr/bluetooth/audio/micp.h | 2 + include/zephyr/bluetooth/audio/pacs.h | 4 ++ include/zephyr/bluetooth/audio/pbp.h | 6 +- include/zephyr/bluetooth/audio/tbs.h | 1 + include/zephyr/bluetooth/audio/tmap.h | 2 + include/zephyr/bluetooth/audio/vcp.h | 2 + subsys/bluetooth/audio/aics.c | 26 ++++++-- subsys/bluetooth/audio/aics_client.c | 27 +++++--- subsys/bluetooth/audio/aics_internal.h | 9 ++- subsys/bluetooth/audio/ascs.c | 37 +++++++---- subsys/bluetooth/audio/ascs_internal.h | 9 +++ subsys/bluetooth/audio/audio.c | 14 +++- subsys/bluetooth/audio/audio_internal.h | 7 +- subsys/bluetooth/audio/bap_base.c | 15 ++++- .../bluetooth/audio/bap_broadcast_assistant.c | 30 +++++++-- subsys/bluetooth/audio/bap_broadcast_sink.c | 32 +++++++--- subsys/bluetooth/audio/bap_broadcast_source.c | 23 +++++-- subsys/bluetooth/audio/bap_endpoint.h | 9 +++ subsys/bluetooth/audio/bap_internal.h | 9 ++- subsys/bluetooth/audio/bap_iso.c | 17 ++++- subsys/bluetooth/audio/bap_iso.h | 7 +- subsys/bluetooth/audio/bap_scan_delegator.c | 31 ++++++--- subsys/bluetooth/audio/bap_stream.c | 23 +++++-- subsys/bluetooth/audio/bap_stream.h | 8 +++ subsys/bluetooth/audio/bap_unicast_client.c | 47 ++++++++------ .../audio/bap_unicast_client_internal.h | 8 +++ subsys/bluetooth/audio/bap_unicast_server.c | 17 +++-- subsys/bluetooth/audio/bap_unicast_server.h | 3 + subsys/bluetooth/audio/cap_acceptor.c | 15 ++++- subsys/bluetooth/audio/cap_commander.c | 26 ++++++-- subsys/bluetooth/audio/cap_initiator.c | 4 +- subsys/bluetooth/audio/cap_internal.h | 12 ++-- subsys/bluetooth/audio/cap_stream.c | 5 +- subsys/bluetooth/audio/ccid.c | 5 ++ subsys/bluetooth/audio/ccid_internal.h | 4 +- subsys/bluetooth/audio/codec.c | 12 +++- subsys/bluetooth/audio/csip_crypto.c | 11 +++- subsys/bluetooth/audio/csip_crypto.h | 4 +- subsys/bluetooth/audio/csip_internal.h | 5 +- subsys/bluetooth/audio/csip_set_coordinator.c | 36 +++++++---- subsys/bluetooth/audio/csip_set_member.c | 40 ++++++++---- subsys/bluetooth/audio/gmap_client.c | 14 +++- subsys/bluetooth/audio/gmap_server.c | 18 ++++-- subsys/bluetooth/audio/has.c | 38 ++++++++--- subsys/bluetooth/audio/has_client.c | 21 ++++-- subsys/bluetooth/audio/has_internal.h | 6 ++ subsys/bluetooth/audio/mcc.c | 41 +++++++----- subsys/bluetooth/audio/mcc_internal.h | 9 ++- subsys/bluetooth/audio/mcs.c | 34 ++++++---- subsys/bluetooth/audio/mcs_internal.h | 5 +- subsys/bluetooth/audio/media_proxy.c | 13 ++-- subsys/bluetooth/audio/media_proxy_internal.h | 4 ++ subsys/bluetooth/audio/micp_internal.h | 6 +- subsys/bluetooth/audio/micp_mic_ctlr.c | 32 ++++++---- subsys/bluetooth/audio/micp_mic_dev.c | 27 +++++--- subsys/bluetooth/audio/mpl.c | 32 ++++++---- subsys/bluetooth/audio/mpl_internal.h | 7 ++ subsys/bluetooth/audio/pacs.c | 43 ++++++++----- subsys/bluetooth/audio/pacs_internal.h | 4 +- subsys/bluetooth/audio/pbp.c | 13 +++- subsys/bluetooth/audio/shell/audio.h | 18 +++++- subsys/bluetooth/audio/shell/bap.c | 44 +++++++++---- .../audio/shell/bap_broadcast_assistant.c | 28 +++++--- .../audio/shell/bap_scan_delegator.c | 30 ++++++--- subsys/bluetooth/audio/shell/bap_usb.c | 15 ++++- subsys/bluetooth/audio/shell/cap_acceptor.c | 18 +++++- subsys/bluetooth/audio/shell/cap_commander.c | 8 ++- subsys/bluetooth/audio/shell/cap_initiator.c | 21 +++++- .../audio/shell/csip_set_coordinator.c | 27 +++++--- .../bluetooth/audio/shell/csip_set_member.c | 24 +++++-- subsys/bluetooth/audio/shell/gmap.c | 15 ++++- subsys/bluetooth/audio/shell/has.c | 15 +++-- subsys/bluetooth/audio/shell/has_client.c | 11 +++- subsys/bluetooth/audio/shell/mcc.c | 21 ++++-- .../bluetooth/audio/shell/media_controller.c | 26 +++++--- subsys/bluetooth/audio/shell/micp_mic_ctlr.c | 15 +++-- subsys/bluetooth/audio/shell/micp_mic_dev.c | 17 +++-- subsys/bluetooth/audio/shell/mpl.c | 14 ++-- subsys/bluetooth/audio/shell/pbp.c | 12 +++- subsys/bluetooth/audio/shell/tbs.c | 15 ++++- subsys/bluetooth/audio/shell/tbs_client.c | 18 ++++-- subsys/bluetooth/audio/shell/tmap.c | 5 ++ subsys/bluetooth/audio/shell/vcp_vol_ctlr.c | 15 ++++- subsys/bluetooth/audio/shell/vcp_vol_rend.c | 19 ++++-- subsys/bluetooth/audio/tbs.c | 27 +++++--- subsys/bluetooth/audio/tbs_client.c | 35 ++++++---- subsys/bluetooth/audio/tbs_internal.h | 10 ++- subsys/bluetooth/audio/tmap.c | 28 ++++---- subsys/bluetooth/audio/vcp_internal.h | 8 +++ subsys/bluetooth/audio/vcp_vol_ctlr.c | 40 +++++++----- subsys/bluetooth/audio/vcp_vol_rend.c | 34 +++++++--- subsys/bluetooth/audio/vocs.c | 32 +++++++--- subsys/bluetooth/audio/vocs_client.c | 31 +++++---- subsys/bluetooth/audio/vocs_internal.h | 10 ++- .../audio/src/bap_bass_broadcaster_test.c | 11 ++++ .../audio/src/bap_broadcast_assistant_test.c | 20 +++++- .../audio/src/bap_broadcast_sink_test.c | 26 +++++++- .../audio/src/bap_broadcast_source_test.c | 22 ++++++- tests/bsim/bluetooth/audio/src/bap_common.c | 9 +++ tests/bsim/bluetooth/audio/src/bap_common.h | 5 +- .../audio/src/bap_scan_delegator_test.c | 22 ++++++- .../audio/src/bap_unicast_client_test.c | 29 +++++++-- .../audio/src/bap_unicast_server_test.c | 27 ++++++-- .../bluetooth/audio/src/cap_acceptor_test.c | 32 ++++++++-- .../bluetooth/audio/src/cap_commander_test.c | 23 +++++-- .../audio/src/cap_initiator_broadcast_test.c | 26 ++++++-- .../audio/src/cap_initiator_unicast_test.c | 33 ++++++++-- tests/bsim/bluetooth/audio/src/common.c | 23 ++++++- tests/bsim/bluetooth/audio/src/common.h | 22 ++++--- .../audio/src/csip_notify_client_test.c | 9 ++- .../audio/src/csip_notify_server_test.c | 14 +++- .../audio/src/csip_set_coordinator_test.c | 21 +++++- .../audio/src/csip_set_member_test.c | 14 +++- .../bsim/bluetooth/audio/src/gmap_ugg_test.c | 29 +++++++-- .../bsim/bluetooth/audio/src/gmap_ugt_test.c | 25 ++++++-- .../bluetooth/audio/src/has_client_test.c | 16 ++++- tests/bsim/bluetooth/audio/src/has_test.c | 12 +++- .../bluetooth/audio/src/ias_client_test.c | 10 ++- tests/bsim/bluetooth/audio/src/ias_test.c | 10 +-- tests/bsim/bluetooth/audio/src/main.c | 2 + tests/bsim/bluetooth/audio/src/mcc_test.c | 20 ++++-- tests/bsim/bluetooth/audio/src/mcs_test.c | 8 ++- .../audio/src/media_controller_test.c | 16 +++-- .../bluetooth/audio/src/micp_mic_ctlr_test.c | 11 +++- .../bluetooth/audio/src/micp_mic_dev_test.c | 14 +++- .../audio/src/pacs_notify_client_test.c | 11 ++++ .../audio/src/pacs_notify_server_test.c | 17 ++++- .../src/pbp_public_broadcast_sink_test.c | 23 +++++-- .../src/pbp_public_broadcast_source_test.c | 25 ++++++-- .../bluetooth/audio/src/tbs_client_test.c | 30 +++++---- tests/bsim/bluetooth/audio/src/tbs_test.c | 64 +++++++++++-------- .../bluetooth/audio/src/tmap_client_test.c | 17 +++-- .../bluetooth/audio/src/tmap_server_test.c | 17 ++--- .../bluetooth/audio/src/vcp_vol_ctlr_test.c | 14 ++-- .../bluetooth/audio/src/vcp_vol_rend_test.c | 13 +++- 146 files changed, 1924 insertions(+), 612 deletions(-) diff --git a/include/zephyr/bluetooth/audio/aics.h b/include/zephyr/bluetooth/audio/aics.h index 55f2eab2f931ab..a554c1503959ab 100644 --- a/include/zephyr/bluetooth/audio/aics.h +++ b/include/zephyr/bluetooth/audio/aics.h @@ -27,7 +27,10 @@ * autonomously read the change counter value when executing a write request. * */ +#include +#include +#include #include #ifdef __cplusplus diff --git a/include/zephyr/bluetooth/audio/audio.h b/include/zephyr/bluetooth/audio/audio.h index 0578f632bd2f40..5bc503f5a3d73e 100644 --- a/include/zephyr/bluetooth/audio/audio.h +++ b/include/zephyr/bluetooth/audio/audio.h @@ -18,14 +18,21 @@ * @{ */ -#include +#include +#include +#include + +#include +#include +#include #include #include +#include #include #include -#include -#include - +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -1011,7 +1018,7 @@ int bt_audio_codec_cfg_set_chan_allocation(struct bt_audio_codec_cfg *codec_cfg, * * The overall SDU size will be octets_per_frame * blocks_per_sdu. * - * The Bluetooth specificationa are not clear about this value - it does not state that + * The Bluetooth specifications are not clear about this value - it does not state that * the codec shall use this SDU size only. A codec like LC3 supports variable bit-rate * (per SDU) hence it might be allowed for an encoder to reduce the frame size below this * value. @@ -1040,7 +1047,7 @@ int bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg *cod int bt_audio_codec_cfg_set_octets_per_frame(struct bt_audio_codec_cfg *codec_cfg, uint16_t octets_per_frame); -/** @brief Extract number of audio frame blockss in each SDU from BT codec config +/** @brief Extract number of audio frame blocks in each SDU from BT codec config * * The overall SDU size will be octets_per_frame * frame_blocks_per_sdu * number-of-channels. * diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h index 32d9840c5be5bb..00957b2b81be54 100644 --- a/include/zephyr/bluetooth/audio/bap.h +++ b/include/zephyr/bluetooth/audio/bap.h @@ -17,9 +17,17 @@ * @{ */ -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/bap_lc3_preset.h b/include/zephyr/bluetooth/audio/bap_lc3_preset.h index d31c47fd4fb792..7ba6af250a2169 100644 --- a/include/zephyr/bluetooth/audio/bap_lc3_preset.h +++ b/include/zephyr/bluetooth/audio/bap_lc3_preset.h @@ -10,6 +10,7 @@ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_BAP_LC3_PRESET_ #include +#include /** Struct to hold a BAP defined LC3 preset */ struct bt_bap_lc3_preset { diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index c5c4bbea6e8aed..afc1ca9018ef05 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -19,12 +19,18 @@ * @{ */ +#include +#include #include -#include -#include #include #include +#include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/csip.h b/include/zephyr/bluetooth/audio/csip.h index 6f3a028024236a..7b8d8d2631fe40 100644 --- a/include/zephyr/bluetooth/audio/csip.h +++ b/include/zephyr/bluetooth/audio/csip.h @@ -19,7 +19,16 @@ * @{ */ +#include +#include +#include + +#include +#include #include +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/gmap_lc3_preset.h b/include/zephyr/bluetooth/audio/gmap_lc3_preset.h index e5a22936c741e3..5e50de243e7fdb 100644 --- a/include/zephyr/bluetooth/audio/gmap_lc3_preset.h +++ b/include/zephyr/bluetooth/audio/gmap_lc3_preset.h @@ -9,7 +9,9 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_GMAP_LC3_PRESET_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_GMAP_LC3_PRESET_ +#include #include +#include /* GMAP LC3 unicast presets defined by table 3.16 in the GMAP v1.0 specification */ diff --git a/include/zephyr/bluetooth/audio/has.h b/include/zephyr/bluetooth/audio/has.h index 0e5c165290215d..7bd20aec89e3aa 100644 --- a/include/zephyr/bluetooth/audio/has.h +++ b/include/zephyr/bluetooth/audio/has.h @@ -22,10 +22,12 @@ * to control hearing aid presets. */ -#include +#include +#include #include #include +#include #ifdef __cplusplus extern "C" { @@ -63,7 +65,7 @@ enum bt_has_properties { BT_HAS_PROP_AVAILABLE = BIT(1), }; -/** Hearing Aid device capablilities */ +/** Hearing Aid device capabilities */ enum bt_has_capabilities { BT_HAS_PRESET_SUPPORT = BIT(0), }; diff --git a/include/zephyr/bluetooth/audio/mcc.h b/include/zephyr/bluetooth/audio/mcc.h index 14dba829225301..fb71f011db96ef 100644 --- a/include/zephyr/bluetooth/audio/mcc.h +++ b/include/zephyr/bluetooth/audio/mcc.h @@ -22,6 +22,7 @@ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MCC_ #include +#include #include #include @@ -407,7 +408,7 @@ typedef void (*bt_mcc_read_content_control_id_cb)(struct bt_conn *conn, typedef void (*bt_mcc_otc_obj_selected_cb)(struct bt_conn *conn, int err); /** - * @brief Callback function for bt_mcc_otc_read_object_meatadata() + * @brief Callback function for bt_mcc_otc_read_object_metadata() * * Called when object metadata is read * diff --git a/include/zephyr/bluetooth/audio/mcs.h b/include/zephyr/bluetooth/audio/mcs.h index 7d9491944ef275..5212905497c276 100644 --- a/include/zephyr/bluetooth/audio/mcs.h +++ b/include/zephyr/bluetooth/audio/mcs.h @@ -23,6 +23,7 @@ */ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/media_proxy.h b/include/zephyr/bluetooth/audio/media_proxy.h index 0e236a1fd4a072..16bb978bfcc48b 100644 --- a/include/zephyr/bluetooth/audio/media_proxy.h +++ b/include/zephyr/bluetooth/audio/media_proxy.h @@ -40,6 +40,7 @@ #include #include +#include /* TODO: Remove dependency on mcs.h */ #include "mcs.h" diff --git a/include/zephyr/bluetooth/audio/micp.h b/include/zephyr/bluetooth/audio/micp.h index 500eb2048395f3..0fe9a7af681f5e 100644 --- a/include/zephyr/bluetooth/audio/micp.h +++ b/include/zephyr/bluetooth/audio/micp.h @@ -22,6 +22,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/pacs.h b/include/zephyr/bluetooth/audio/pacs.h index 6db4d34b0a285b..74f401d7bd54fe 100644 --- a/include/zephyr/bluetooth/audio/pacs.h +++ b/include/zephyr/bluetooth/audio/pacs.h @@ -10,7 +10,11 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_PACS_H_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_PACS_H_ +#include + #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/pbp.h b/include/zephyr/bluetooth/audio/pbp.h index 71d7d107b4e9c8..d218720895d34a 100644 --- a/include/zephyr/bluetooth/audio/pbp.h +++ b/include/zephyr/bluetooth/audio/pbp.h @@ -19,8 +19,12 @@ * @{ */ -#include #include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/tbs.h b/include/zephyr/bluetooth/audio/tbs.h index 523efc4264fc1d..49039a7ff6145f 100644 --- a/include/zephyr/bluetooth/audio/tbs.h +++ b/include/zephyr/bluetooth/audio/tbs.h @@ -14,6 +14,7 @@ #include #include +#include /* Call States */ #define BT_TBS_CALL_STATE_INCOMING 0x00 diff --git a/include/zephyr/bluetooth/audio/tmap.h b/include/zephyr/bluetooth/audio/tmap.h index 4bcdbb0a5bfc81..1c8e8ccb8921d5 100644 --- a/include/zephyr/bluetooth/audio/tmap.h +++ b/include/zephyr/bluetooth/audio/tmap.h @@ -9,8 +9,10 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TMAP_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TMAP_ +#include #include #include +#include /** Call Gateway (CG) supported */ #define BT_TMAP_CG_SUPPORTED \ diff --git a/include/zephyr/bluetooth/audio/vcp.h b/include/zephyr/bluetooth/audio/vcp.h index 1128bf18d1e4b7..755ee12d065abd 100644 --- a/include/zephyr/bluetooth/audio/vcp.h +++ b/include/zephyr/bluetooth/audio/vcp.h @@ -23,6 +23,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/subsys/bluetooth/audio/aics.c b/subsys/bluetooth/audio/aics.c index 1e42cc73da52df..222969aba241bf 100644 --- a/subsys/bluetooth/audio/aics.c +++ b/subsys/bluetooth/audio/aics.c @@ -5,17 +5,29 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include - -#include -#include - +#include +#include +#include +#include +#include +#include + +#include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "aics_internal.h" #include "audio_internal.h" diff --git a/subsys/bluetooth/audio/aics_client.c b/subsys/bluetooth/audio/aics_client.c index 943f6475a38d70..332f5a7fabff5d 100644 --- a/subsys/bluetooth/audio/aics_client.c +++ b/subsys/bluetooth/audio/aics_client.c @@ -7,24 +7,31 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include - -#include - -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "aics_internal.h" -#include - LOG_MODULE_REGISTER(bt_aics_client, CONFIG_BT_AICS_CLIENT_LOG_LEVEL); static struct bt_aics aics_insts[CONFIG_BT_MAX_CONN * CONFIG_BT_AICS_CLIENT_MAX_INSTANCE_COUNT]; diff --git a/subsys/bluetooth/audio/aics_internal.h b/subsys/bluetooth/audio/aics_internal.h index 3c10287a0f311e..4283abce2fb580 100644 --- a/subsys/bluetooth/audio/aics_internal.h +++ b/subsys/bluetooth/audio/aics_internal.h @@ -11,8 +11,15 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_AICS_INTERNAL_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_AICS_INTERNAL_ -#include +#include +#include + +#include +#include #include +#include +#include +#include #if defined(CONFIG_BT_AICS) #define BT_AICS_MAX_DESC_SIZE CONFIG_BT_AICS_MAX_INPUT_DESCRIPTION_SIZE diff --git a/subsys/bluetooth/audio/ascs.c b/subsys/bluetooth/audio/ascs.c index 31e7bcca133505..2528cc00b13f08 100644 --- a/subsys/bluetooth/audio/ascs.c +++ b/subsys/bluetooth/audio/ascs.c @@ -7,20 +7,33 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -#include -#include -#include - +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include #include +#include #include -#include -#include -#include - +#include +#include #include +#include +#include +#include +#include +#include +#include +#include LOG_MODULE_REGISTER(bt_ascs, CONFIG_BT_ASCS_LOG_LEVEL); @@ -29,9 +42,11 @@ LOG_MODULE_REGISTER(bt_ascs, CONFIG_BT_ASCS_LOG_LEVEL); #include "../host/att_internal.h" +#include "ascs_internal.h" #include "audio_internal.h" -#include "bap_iso.h" #include "bap_endpoint.h" +#include "bap_iso.h" +#include "bap_stream.h" #include "bap_unicast_server.h" #include "pacs_internal.h" #include "cap_internal.h" @@ -1680,7 +1695,7 @@ int bt_ascs_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream, return -EALREADY; } - /* Get a free ASE or NULL if all ASE instances are aready in use */ + /* Get a free ASE or NULL if all ASE instances are already in use */ for (int i = 1; i <= ASE_COUNT; i++) { if (ase_find(conn, i) == NULL) { ase = ase_new(conn, i); diff --git a/subsys/bluetooth/audio/ascs_internal.h b/subsys/bluetooth/audio/ascs_internal.h index fc76964a01837a..f96a1905ec5252 100644 --- a/subsys/bluetooth/audio/ascs_internal.h +++ b/subsys/bluetooth/audio/ascs_internal.h @@ -7,6 +7,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +#ifndef BT_ASCS_INTERNAL_H +#define BT_ASCS_INTERNAL_H + +#include +#include +#include + #define BT_ASCS_ASE_ID_NONE 0x00 /* The number of ASEs in the notification when the opcode is unsupported or the length of the @@ -349,3 +356,5 @@ int bt_ascs_disable_ase(struct bt_bap_ep *ep); int bt_ascs_release_ase(struct bt_bap_ep *ep); void bt_ascs_foreach_ep(struct bt_conn *conn, bt_bap_ep_func_t func, void *user_data); + +#endif /* BT_ASCS_INTERNAL_H */ diff --git a/subsys/bluetooth/audio/audio.c b/subsys/bluetooth/audio/audio.c index 619f52c7abc2e0..f38ec14c00130f 100644 --- a/subsys/bluetooth/audio/audio.c +++ b/subsys/bluetooth/audio/audio.c @@ -6,11 +6,21 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include +#include + +#include +#include +#include #include +#include #include +#include #include -#include -#include +#include #include #include diff --git a/subsys/bluetooth/audio/audio_internal.h b/subsys/bluetooth/audio/audio_internal.h index f13e130089a11f..b6fde6118f4641 100644 --- a/subsys/bluetooth/audio/audio_internal.h +++ b/subsys/bluetooth/audio/audio_internal.h @@ -5,9 +5,14 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include -#include +#include #include +#include +#include #define BT_AUDIO_NOTIFY_RETRY_DELAY_US ((CONFIG_BT_AUDIO_NOTIFY_RETRY_DELAY) * 1250U) diff --git a/subsys/bluetooth/audio/bap_base.c b/subsys/bluetooth/audio/bap_base.c index 9d8c2de3933aaf..a649f7446592f5 100644 --- a/subsys/bluetooth/audio/bap_base.c +++ b/subsys/bluetooth/audio/bap_base.c @@ -6,11 +6,24 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include -#include #include +#include #include +#include +#include LOG_MODULE_REGISTER(bt_bap_base, CONFIG_BT_BAP_BASE_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/bap_broadcast_assistant.c b/subsys/bluetooth/audio/bap_broadcast_assistant.c index 90402d2db96ec3..54b5bdd60d68f8 100644 --- a/subsys/bluetooth/audio/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/bap_broadcast_assistant.c @@ -8,20 +8,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include - -#include -#include - +#include +#include +#include +#include +#include + +#include +#include +#include +#include #include #include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include #include @@ -81,7 +97,7 @@ NET_BUF_SIMPLE_DEFINE_STATIC(att_buf, ATT_BUF_SIZE); static int16_t lookup_index_by_handle(uint16_t handle) { - for (int i = 0; i < ARRAY_SIZE(broadcast_assistant.recv_state_handles); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_assistant.recv_state_handles); i++) { if (broadcast_assistant.recv_state_handles[i] == handle) { return i; } diff --git a/subsys/bluetooth/audio/bap_broadcast_sink.c b/subsys/bluetooth/audio/bap_broadcast_sink.c index 97a1206b13a59c..52a4f8da343ddc 100644 --- a/subsys/bluetooth/audio/bap_broadcast_sink.c +++ b/subsys/bluetooth/audio/bap_broadcast_sink.c @@ -6,27 +6,43 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include - +#include +#include +#include +#include +#include + +#include +#include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../host/conn_internal.h" #include "../host/iso_internal.h" +#include "audio_internal.h" #include "bap_iso.h" #include "bap_endpoint.h" -#include "audio_internal.h" - -#include LOG_MODULE_REGISTER(bt_bap_broadcast_sink, CONFIG_BT_BAP_BROADCAST_SINK_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/bap_broadcast_source.c b/subsys/bluetooth/audio/bap_broadcast_source.c index 0934fc0f8d06bd..01e32ae99059dc 100644 --- a/subsys/bluetooth/audio/bap_broadcast_source.c +++ b/subsys/bluetooth/audio/bap_broadcast_source.c @@ -6,21 +6,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include #include - +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include + LOG_MODULE_REGISTER(bt_bap_broadcast_source, CONFIG_BT_BAP_BROADCAST_SOURCE_LOG_LEVEL); #include "bap_iso.h" #include "bap_endpoint.h" +#include "bap_stream.h" struct bt_bap_broadcast_subgroup { /* The streams used to create the broadcast source */ diff --git a/subsys/bluetooth/audio/bap_endpoint.h b/subsys/bluetooth/audio/bap_endpoint.h index 12b1209fb09bdc..4efea0dba67579 100644 --- a/subsys/bluetooth/audio/bap_endpoint.h +++ b/subsys/bluetooth/audio/bap_endpoint.h @@ -7,8 +7,17 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + +#include +#include #include +#include +#include #include +#include +#include #include #include "ascs_internal.h" diff --git a/subsys/bluetooth/audio/bap_internal.h b/subsys/bluetooth/audio/bap_internal.h index 27f62977a22873..905e862c9a2230 100644 --- a/subsys/bluetooth/audio/bap_internal.h +++ b/subsys/bluetooth/audio/bap_internal.h @@ -9,10 +9,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include +#include + #include #include +#include +#include +#include +#include #define BT_BAP_BASS_SCAN_STATE_NOT_SCANNING 0x00 #define BT_BAP_BASS_SCAN_STATE_SCANNING 0x01 diff --git a/subsys/bluetooth/audio/bap_iso.c b/subsys/bluetooth/audio/bap_iso.c index 3fa2059ea94de6..1104fbfb8daa22 100644 --- a/subsys/bluetooth/audio/bap_iso.c +++ b/subsys/bluetooth/audio/bap_iso.c @@ -7,12 +7,25 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "bap_iso.h" #include "audio_internal.h" #include "bap_endpoint.h" -#include - LOG_MODULE_REGISTER(bt_bap_iso, CONFIG_BT_BAP_ISO_LOG_LEVEL); /* TODO: Optimize the ISO_POOL_SIZE */ diff --git a/subsys/bluetooth/audio/bap_iso.h b/subsys/bluetooth/audio/bap_iso.h index 4384182d697fa1..f1ebd0eed9b25d 100644 --- a/subsys/bluetooth/audio/bap_iso.h +++ b/subsys/bluetooth/audio/bap_iso.h @@ -7,9 +7,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include + +#include #include #include +#include +#include struct bt_bap_iso_dir { struct bt_bap_stream *stream; diff --git a/subsys/bluetooth/audio/bap_scan_delegator.c b/subsys/bluetooth/audio/bap_scan_delegator.c index 6a55d7da2c351e..6ba46a49c1f50f 100644 --- a/subsys/bluetooth/audio/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/bap_scan_delegator.c @@ -7,20 +7,35 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include - -#include - +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include +#include #include +#include #include #include - +#include +#include +#include #include +#include +#include +#include +#include +#include +#include LOG_MODULE_REGISTER(bt_bap_scan_delegator, CONFIG_BT_BAP_SCAN_DELEGATOR_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/bap_stream.c b/subsys/bluetooth/audio/bap_stream.c index 0894af516a1b34..fa17e2d138e6f4 100644 --- a/subsys/bluetooth/audio/bap_stream.c +++ b/subsys/bluetooth/audio/bap_stream.c @@ -7,28 +7,39 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../host/iso_internal.h" -#include "bap_iso.h" #include "audio_internal.h" +#include "bap_iso.h" #include "bap_endpoint.h" #include "bap_unicast_client_internal.h" #include "bap_unicast_server.h" -#include - LOG_MODULE_REGISTER(bt_bap_stream, CONFIG_BT_BAP_STREAM_LOG_LEVEL); #if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || \ diff --git a/subsys/bluetooth/audio/bap_stream.h b/subsys/bluetooth/audio/bap_stream.h index 3d02c2cf30c90f..597bf80d94cd61 100644 --- a/subsys/bluetooth/audio/bap_stream.h +++ b/subsys/bluetooth/audio/bap_stream.h @@ -7,6 +7,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + +#include +#include +#include +#include + void bt_bap_stream_init(struct bt_bap_stream *stream); /* Disconnect ISO channel */ diff --git a/subsys/bluetooth/audio/bap_unicast_client.c b/subsys/bluetooth/audio/bap_unicast_client.c index 3de389618f4fe7..236733c9c6bf2d 100644 --- a/subsys/bluetooth/audio/bap_unicast_client.c +++ b/subsys/bluetooth/audio/bap_unicast_client.c @@ -9,28 +9,46 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include - +#include +#include +#include +#include +#include + +#include +#include #include #include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../host/hci_core.h" #include "../host/conn_internal.h" #include "../host/iso_internal.h" -#include "bap_iso.h" +#include "ascs_internal.h" #include "audio_internal.h" +#include "bap_iso.h" #include "bap_endpoint.h" -#include "pacs_internal.h" #include "bap_unicast_client_internal.h" - -#include +#include "pacs_internal.h" BUILD_ASSERT(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 || CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0, @@ -1752,7 +1770,6 @@ static int unicast_client_ep_config(struct bt_bap_ep *ep, struct net_buf_simple const struct bt_audio_codec_cfg *codec_cfg) { struct bt_ascs_config *req; - uint8_t cc_len; LOG_DBG("ep %p buf %p codec %p", ep, buf, codec_cfg); @@ -1784,7 +1801,6 @@ static int unicast_client_ep_config(struct bt_bap_ep *ep, struct net_buf_simple req->codec.cid = codec_cfg->cid; req->codec.vid = codec_cfg->vid; - cc_len = buf->len; req->cc_len = codec_cfg->data_len; net_buf_simple_add_mem(buf, codec_cfg->data, codec_cfg->data_len); @@ -2795,7 +2811,6 @@ int bt_bap_unicast_client_qos(struct bt_conn *conn, struct bt_bap_unicast_group struct net_buf_simple *buf; struct bt_bap_ep *ep; bool conn_stream_found; - bool cig_connected; int err; if (conn == NULL) { @@ -2809,11 +2824,6 @@ int bt_bap_unicast_client_qos(struct bt_conn *conn, struct bt_bap_unicast_group */ conn_stream_found = false; - /* User to determine if any stream in the group is in - * the connected state - */ - cig_connected = false; - /* Validate streams before starting the QoS execution */ SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) { if (stream->conn != conn) { @@ -3292,7 +3302,7 @@ static uint8_t unicast_client_ase_read_func(struct bt_conn *conn, uint8_t err, unicast_client_ep_set_status(ep, buf); cb_err = unicast_client_ep_subscribe(conn, ep); if (cb_err != 0) { - LOG_DBG("Failed to subcribe to ep %p: %d", ep, cb_err); + LOG_DBG("Failed to subscribe to ep %p: %d", ep, cb_err); goto fail; } @@ -3764,7 +3774,6 @@ static uint8_t unicast_client_pacs_context_read_func(struct bt_conn *conn, uint8 struct net_buf_simple buf; struct bt_pacs_context *context; int cb_err; - int index; memset(read, 0, sizeof(*read)); @@ -3777,8 +3786,6 @@ static uint8_t unicast_client_pacs_context_read_func(struct bt_conn *conn, uint8 net_buf_simple_init_with_data(&buf, (void *)data, length); context = net_buf_simple_pull_mem(&buf, sizeof(*context)); - index = bt_conn_index(conn); - discover_loc: /* Read ASE instances */ cb_err = unicast_client_pacs_location_discover(conn); diff --git a/subsys/bluetooth/audio/bap_unicast_client_internal.h b/subsys/bluetooth/audio/bap_unicast_client_internal.h index 56542365ac62d3..8e279ad652d011 100644 --- a/subsys/bluetooth/audio/bap_unicast_client_internal.h +++ b/subsys/bluetooth/audio/bap_unicast_client_internal.h @@ -6,6 +6,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + +#include +#include +#include +#include +#include + int bt_bap_unicast_client_config(struct bt_bap_stream *stream, const struct bt_audio_codec_cfg *codec_cfg); diff --git a/subsys/bluetooth/audio/bap_unicast_server.c b/subsys/bluetooth/audio/bap_unicast_server.c index 911ca7f7d7a47b..0c631186c03a49 100644 --- a/subsys/bluetooth/audio/bap_unicast_server.c +++ b/subsys/bluetooth/audio/bap_unicast_server.c @@ -5,17 +5,24 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include +#include -#include - +#include #include #include +#include +#include +#include +#include +#include "ascs_internal.h" #include "bap_iso.h" -#include "pacs_internal.h" #include "bap_endpoint.h" - -#include +#include "pacs_internal.h" LOG_MODULE_REGISTER(bt_bap_unicast_server, CONFIG_BT_BAP_UNICAST_SERVER_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/bap_unicast_server.h b/subsys/bluetooth/audio/bap_unicast_server.h index 7aef4f4bc2b5ee..34f204e267c3de 100644 --- a/subsys/bluetooth/audio/bap_unicast_server.h +++ b/subsys/bluetooth/audio/bap_unicast_server.h @@ -6,6 +6,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + #include #include diff --git a/subsys/bluetooth/audio/cap_acceptor.c b/subsys/bluetooth/audio/cap_acceptor.c index d84fad1e8fb5f7..f8365eccade357 100644 --- a/subsys/bluetooth/audio/cap_acceptor.c +++ b/subsys/bluetooth/audio/cap_acceptor.c @@ -4,13 +4,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include + +#include #include #include #include -#include "cap_internal.h" - +#include +#include #include +#include +#include + +#include "cap_internal.h" LOG_MODULE_REGISTER(bt_cap_acceptor, CONFIG_BT_CAP_ACCEPTOR_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/cap_commander.c b/subsys/bluetooth/audio/cap_commander.c index fcd28d92fd60dc..8f7d98bac4bf2b 100644 --- a/subsys/bluetooth/audio/cap_commander.c +++ b/subsys/bluetooth/audio/cap_commander.c @@ -4,20 +4,34 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include +#include +#include +#include +#include + +#include +#include #include +#include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bap_endpoint.h" #include "bap_internal.h" #include "cap_internal.h" -#include "ccid_internal.h" #include "csip_internal.h" -#include "bap_endpoint.h" - -#include LOG_MODULE_REGISTER(bt_cap_commander, CONFIG_BT_CAP_COMMANDER_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/cap_initiator.c b/subsys/bluetooth/audio/cap_initiator.c index 61257e8a013e55..f5a6adfde71b2d 100644 --- a/subsys/bluetooth/audio/cap_initiator.c +++ b/subsys/bluetooth/audio/cap_initiator.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -25,10 +27,10 @@ #include #include +#include "bap_endpoint.h" #include "cap_internal.h" #include "ccid_internal.h" #include "csip_internal.h" -#include "bap_endpoint.h" LOG_MODULE_REGISTER(bt_cap_initiator, CONFIG_BT_CAP_INITIATOR_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/cap_internal.h b/subsys/bluetooth/audio/cap_internal.h index e460fce98dcdda..839d4a31757a30 100644 --- a/subsys/bluetooth/audio/cap_internal.h +++ b/subsys/bluetooth/audio/cap_internal.h @@ -8,17 +8,19 @@ #include #include +#include +#include #include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include #include +#include bool bt_cap_acceptor_ccid_exist(const struct bt_conn *conn, uint8_t ccid); diff --git a/subsys/bluetooth/audio/cap_stream.c b/subsys/bluetooth/audio/cap_stream.c index 46009b36a47719..ebebeb2eb5fa22 100644 --- a/subsys/bluetooth/audio/cap_stream.c +++ b/subsys/bluetooth/audio/cap_stream.c @@ -5,10 +5,10 @@ */ #include -#include -#include #include +#include +#include #include #include #include @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/subsys/bluetooth/audio/ccid.c b/subsys/bluetooth/audio/ccid.c index c3a9d6a2b42ea2..60991a54a8b756 100644 --- a/subsys/bluetooth/audio/ccid.c +++ b/subsys/bluetooth/audio/ccid.c @@ -6,9 +6,14 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include + #include #include #include +#include #include "ccid_internal.h" diff --git a/subsys/bluetooth/audio/ccid_internal.h b/subsys/bluetooth/audio/ccid_internal.h index bf48877529d871..b67331f00a3f7a 100644 --- a/subsys/bluetooth/audio/ccid_internal.h +++ b/subsys/bluetooth/audio/ccid_internal.h @@ -10,7 +10,9 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_CCID_H_ #define ZEPHYR_INCLUDE_BLUETOOTH_CCID_H_ -#include +#include + +#include /** * @brief Gets a free CCID value. diff --git a/subsys/bluetooth/audio/codec.c b/subsys/bluetooth/audio/codec.c index 86936d58a8ef94..208448646fc096 100644 --- a/subsys/bluetooth/audio/codec.c +++ b/subsys/bluetooth/audio/codec.c @@ -10,13 +10,21 @@ * Generic Audio. */ +#include +#include +#include +#include #include +#include +#include #include +#include +#include +#include #include #include - -#include +#include LOG_MODULE_REGISTER(bt_audio_codec, CONFIG_BT_AUDIO_CODEC_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/csip_crypto.c b/subsys/bluetooth/audio/csip_crypto.c index 0efe1fec5a26b9..08346bed0bdcc8 100644 --- a/subsys/bluetooth/audio/csip_crypto.c +++ b/subsys/bluetooth/audio/csip_crypto.c @@ -9,16 +9,23 @@ * in the CSIS spec is also provided as BE, and logging values as BE will make * it easier to compare. */ -#include "csip_crypto.h" +#include +#include +#include + +#include +#include #include +#include #include #include +#include #include "crypto/bt_crypto.h" #include "common/bt_str.h" -#include +#include "csip_crypto.h" LOG_MODULE_REGISTER(bt_csip_crypto, CONFIG_BT_CSIP_SET_MEMBER_CRYPTO_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/csip_crypto.h b/subsys/bluetooth/audio/csip_crypto.h index 1a41bf32d547ee..b522eb94a98a32 100644 --- a/subsys/bluetooth/audio/csip_crypto.h +++ b/subsys/bluetooth/audio/csip_crypto.h @@ -5,10 +5,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include #include +#include #define BT_CSIP_CRYPTO_KEY_SIZE 16 #define BT_CSIP_CRYPTO_SALT_SIZE 16 diff --git a/subsys/bluetooth/audio/csip_internal.h b/subsys/bluetooth/audio/csip_internal.h index 6335e664c40a5a..0ac61f335c0bf6 100644 --- a/subsys/bluetooth/audio/csip_internal.h +++ b/subsys/bluetooth/audio/csip_internal.h @@ -7,8 +7,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include #define BT_CSIP_SIRK_TYPE_ENCRYPTED 0x00 #define BT_CSIP_SIRK_TYPE_PLAIN 0x01 diff --git a/subsys/bluetooth/audio/csip_set_coordinator.c b/subsys/bluetooth/audio/csip_set_coordinator.c index b9d6f251a8bc7d..fea61e131b67c7 100644 --- a/subsys/bluetooth/audio/csip_set_coordinator.c +++ b/subsys/bluetooth/audio/csip_set_coordinator.c @@ -18,27 +18,41 @@ * 10) Unlock all members */ +#include +#include +#include +#include #include -#include -#include - -#include -#include -#include +#include +#include +#include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include "csip_crypto.h" -#include "csip_internal.h" + #include "../host/conn_internal.h" #include "../host/keys.h" -#include "common/bt_str.h" -#include +#include "csip_crypto.h" +#include "csip_internal.h" +#include "common/bt_str.h" LOG_MODULE_REGISTER(bt_csip_set_coordinator, CONFIG_BT_CSIP_SET_COORDINATOR_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/csip_set_member.c b/subsys/bluetooth/audio/csip_set_member.c index d038020f9c8a90..f3e91beb8a5558 100644 --- a/subsys/bluetooth/audio/csip_set_member.c +++ b/subsys/bluetooth/audio/csip_set_member.c @@ -6,37 +6,51 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -#include -#include - -#include -#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include "audio_internal.h" -#include "csip_internal.h" -#include "csip_crypto.h" #include "../host/conn_internal.h" #include "../host/hci_core.h" #include "../host/keys.h" +#include "common/bt_str.h" +#include "audio_internal.h" +#include "csip_internal.h" +#include "csip_crypto.h" + #define CSIP_SET_LOCK_TIMER_VALUE K_SECONDS(60) #define CSIS_CHAR_ATTR_COUNT 3 /* declaration + value + cccd */ #define CSIS_RANK_CHAR_ATTR_COUNT 2 /* declaration + value */ -#include "common/bt_str.h" - -#include - LOG_MODULE_REGISTER(bt_csip_set_member, CONFIG_BT_CSIP_SET_MEMBER_LOG_LEVEL); enum csip_flag { diff --git a/subsys/bluetooth/audio/gmap_client.c b/subsys/bluetooth/audio/gmap_client.c index dff67356b760be..8f4fb74ffa0665 100644 --- a/subsys/bluetooth/audio/gmap_client.c +++ b/subsys/bluetooth/audio/gmap_client.c @@ -4,9 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include +#include + +#include +#include #include +#include +#include +#include #include +#include +#include #include #include "audio_internal.h" diff --git a/subsys/bluetooth/audio/gmap_server.c b/subsys/bluetooth/audio/gmap_server.c index 5bc16ee686f154..d80003bf210a79 100644 --- a/subsys/bluetooth/audio/gmap_server.c +++ b/subsys/bluetooth/audio/gmap_server.c @@ -3,12 +3,22 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -#include +#include +#include +#include +#include +#include +#include + +#include #include -#include - +#include +#include +#include #include +#include +#include +#include #include "audio_internal.h" diff --git a/subsys/bluetooth/audio/has.c b/subsys/bluetooth/audio/has.c index b018e034bb7b63..f90c54159cd31a 100644 --- a/subsys/bluetooth/audio/has.c +++ b/subsys/bluetooth/audio/has.c @@ -4,24 +4,42 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include - -#include -#include +#include +#include +#include +#include +#include +#include + +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include +#include #include "../bluetooth/host/hci_core.h" #include "../bluetooth/host/settings.h" -#include "audio_internal.h" -#include "has_internal.h" +#include "audio_internal.h" #include "common/bt_str.h" - -#include +#include "has_internal.h" LOG_MODULE_REGISTER(bt_has, CONFIG_BT_HAS_LOG_LEVEL); @@ -184,7 +202,7 @@ static struct client_context { uint8_t last_preset_index_known; } contexts[CONFIG_BT_MAX_PAIRED]; -/* Connected client clientance */ +/* Connected client instance */ static struct has_client { struct bt_conn *conn; #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) @@ -919,7 +937,7 @@ static int settings_set_cb(const char *name, size_t len_rd, settings_read_cb rea return 0; } -BT_SETTINGS_DEFINE(has, "has", settings_set_cb, NULL); +static BT_SETTINGS_DEFINE(has, "has", settings_set_cb, NULL); static void store_client_context(struct client_context *context) { diff --git a/subsys/bluetooth/audio/has_client.c b/subsys/bluetooth/audio/has_client.c index 9ac33139a965c9..0426cf9dbe3a9d 100644 --- a/subsys/bluetooth/audio/has_client.c +++ b/subsys/bluetooth/audio/has_client.c @@ -3,20 +3,29 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -#include - +#include +#include +#include +#include +#include + +#include +#include +#include #include +#include #include -#include +#include +#include +#include #include #include #include +#include +#include #include "has_internal.h" -#include - LOG_MODULE_REGISTER(bt_has_client, CONFIG_BT_HAS_CLIENT_LOG_LEVEL); #define HAS_INST(_has) CONTAINER_OF(_has, struct bt_has_client, has) diff --git a/subsys/bluetooth/audio/has_internal.h b/subsys/bluetooth/audio/has_internal.h index 5c5dc6b9410932..97b4d2017aefa0 100644 --- a/subsys/bluetooth/audio/has_internal.h +++ b/subsys/bluetooth/audio/has_internal.h @@ -8,8 +8,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + #include #include +#include +#include +#include /* Control Point opcodes */ #define BT_HAS_OP_READ_PRESET_REQ 0x01 diff --git a/subsys/bluetooth/audio/mcc.c b/subsys/bluetooth/audio/mcc.c index e192c0352dba8a..38929ab19cdd27 100644 --- a/subsys/bluetooth/audio/mcc.c +++ b/subsys/bluetooth/audio/mcc.c @@ -7,22 +7,38 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include - +#include +#include +#include +#include +#include #include #include #include -#include -#include "mcc_internal.h" - #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "../services/ots/ots_client_internal.h" +#include "common/bt_str.h" +#include "mcc_internal.h" #include "mcs_internal.h" /* TODO: Temporarily copied here from media_proxy_internal.h - clean up */ @@ -38,13 +54,8 @@ } \ } while (0) - -#include - LOG_MODULE_REGISTER(bt_mcc, CONFIG_BT_MCC_LOG_LEVEL); -#include "common/bt_str.h" - static struct mcs_instance_t mcs_instance; static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0); diff --git a/subsys/bluetooth/audio/mcc_internal.h b/subsys/bluetooth/audio/mcc_internal.h index 2838e53ba350d8..603977a70f3f90 100644 --- a/subsys/bluetooth/audio/mcc_internal.h +++ b/subsys/bluetooth/audio/mcc_internal.h @@ -11,10 +11,15 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MCP_INTERNAL_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MCP_INTERNAL_ -#include +#include +#include + +#include +#include +#include #include #include -#include "../services/ots/ots_client_internal.h" +#include struct mcs_instance_t *lookup_inst_by_conn(struct bt_conn *conn); diff --git a/subsys/bluetooth/audio/mcs.c b/subsys/bluetooth/audio/mcs.c index 271ea690ad7351..d0eb2f7658bb3f 100644 --- a/subsys/bluetooth/audio/mcs.c +++ b/subsys/bluetooth/audio/mcs.c @@ -8,29 +8,37 @@ * SPDX-License-Identifier: Apache-2.0 */ - -#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include #include +#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "audio_internal.h" #include "media_proxy_internal.h" #include "mcs_internal.h" -#include - LOG_MODULE_REGISTER(bt_mcs, CONFIG_BT_MCS_LOG_LEVEL); static void notify(const struct bt_uuid *uuid, const void *data, uint16_t len); @@ -986,7 +994,7 @@ static void notify_string(struct bt_conn *conn, const struct bt_uuid *uuid, cons __ASSERT(att_mtu > att_header_size, "Could not get valid ATT MTU"); maxlen = att_mtu - att_header_size; /* Subtract opcode and handle */ - /* Send notifcation potentially truncated to the MTU */ + /* Send notification potentially truncated to the MTU */ err = bt_gatt_notify_uuid(conn, uuid, mcs.attrs, (void *)str, MIN(strlen(str), maxlen)); if (err != 0) { diff --git a/subsys/bluetooth/audio/mcs_internal.h b/subsys/bluetooth/audio/mcs_internal.h index 3bbce49fa14921..e2a16049541ff3 100644 --- a/subsys/bluetooth/audio/mcs_internal.h +++ b/subsys/bluetooth/audio/mcs_internal.h @@ -8,9 +8,8 @@ #ifndef ZEPHYR_SUBSYS_BLUETOOTH_HOST_AUDIO_MCS_INTERNAL_H_ #define ZEPHYR_SUBSYS_BLUETOOTH_HOST_AUDIO_MCS_INTERNAL_H_ -#include -#include -#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/subsys/bluetooth/audio/media_proxy.c b/subsys/bluetooth/audio/media_proxy.c index e816b1f20a00b6..54e567de101953 100644 --- a/subsys/bluetooth/audio/media_proxy.c +++ b/subsys/bluetooth/audio/media_proxy.c @@ -6,17 +6,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include -#include +#include #include #include +#include +#include +#include +#include #include "media_proxy_internal.h" #include "mcs_internal.h" -#include - LOG_MODULE_REGISTER(media_proxy, CONFIG_MCTL_LOG_LEVEL); /* Media player */ diff --git a/subsys/bluetooth/audio/media_proxy_internal.h b/subsys/bluetooth/audio/media_proxy_internal.h index 37f5e5997674be..6a24f80d11b814 100644 --- a/subsys/bluetooth/audio/media_proxy_internal.h +++ b/subsys/bluetooth/audio/media_proxy_internal.h @@ -9,7 +9,11 @@ /** @brief Internal APIs for Bluetooth Media Control */ +#include + +#include #include +#include #define MPL_NO_TRACK_ID 0 diff --git a/subsys/bluetooth/audio/micp_internal.h b/subsys/bluetooth/audio/micp_internal.h index ce486bf6fe6c0b..d23d655133bc45 100644 --- a/subsys/bluetooth/audio/micp_internal.h +++ b/subsys/bluetooth/audio/micp_internal.h @@ -12,7 +12,11 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MICP_INTERNAL_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MICP_INTERNAL_ -#include +#include +#include + +#include +#include #include struct bt_micp_mic_ctlr { diff --git a/subsys/bluetooth/audio/micp_mic_ctlr.c b/subsys/bluetooth/audio/micp_mic_ctlr.c index 45190b7c9b4ca0..9b3605f7efe8b4 100644 --- a/subsys/bluetooth/audio/micp_mic_ctlr.c +++ b/subsys/bluetooth/audio/micp_mic_ctlr.c @@ -7,26 +7,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include - -#include - -#include -#include - +#include +#include +#include +#include +#include + +#include +#include +#include +#include #include #include #include -#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include "common/bt_str.h" #include "micp_internal.h" LOG_MODULE_REGISTER(bt_micp_mic_ctlr, CONFIG_BT_MICP_MIC_CTLR_LOG_LEVEL); -#include "common/bt_str.h" - /* Callback functions */ static sys_slist_t micp_mic_ctlr_cbs = SYS_SLIST_STATIC_INIT(&micp_mic_ctlr_cbs); diff --git a/subsys/bluetooth/audio/micp_mic_dev.c b/subsys/bluetooth/audio/micp_mic_dev.c index e282845936aa91..1bc1e10b43e7a8 100644 --- a/subsys/bluetooth/audio/micp_mic_dev.c +++ b/subsys/bluetooth/audio/micp_mic_dev.c @@ -6,23 +6,32 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include - -#include -#include - +#include +#include +#include +#include +#include + +#include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "audio_internal.h" -#include - LOG_MODULE_REGISTER(bt_micp, CONFIG_BT_MICP_MIC_DEV_LOG_LEVEL); struct bt_micp_server { diff --git a/subsys/bluetooth/audio/mpl.c b/subsys/bluetooth/audio/mpl.c index 111482b3e04c96..a80429ee80e311 100644 --- a/subsys/bluetooth/audio/mpl.c +++ b/subsys/bluetooth/audio/mpl.c @@ -6,25 +6,35 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include - +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include #include #include +#include -#include -#include - +#include "ccid_internal.h" #include "media_proxy_internal.h" +#include "mcs_internal.h" #include "mpl_internal.h" -#include - LOG_MODULE_REGISTER(bt_mpl, CONFIG_BT_MPL_LOG_LEVEL); -#include "ccid_internal.h" -#include "mcs_internal.h" - #define TRACK_STATUS_INVALID 0x00 #define TRACK_STATUS_VALID 0x01 @@ -395,7 +405,7 @@ static uint32_t setup_parent_group_object(struct mpl_group *group) /* The implementation has a fixed structure, with one parent group, */ /* and one level of groups containing tracks only. */ /* The track groups have a pointer to the parent, but there is no */ - /* poinbter in the other direction, so it is not possible to go from */ + /* pointer in the other direction, so it is not possible to go from */ /* the parent group to a group of tracks. */ uint8_t type = MEDIA_PROXY_GROUP_OBJECT_GROUP_TYPE; diff --git a/subsys/bluetooth/audio/mpl_internal.h b/subsys/bluetooth/audio/mpl_internal.h index c8a553da2166d9..e24441371927ee 100644 --- a/subsys/bluetooth/audio/mpl_internal.h +++ b/subsys/bluetooth/audio/mpl_internal.h @@ -10,6 +10,13 @@ #ifndef ZEPHYR_SUBSYS_BLUETOOTH_AUDIO_MPL_INTERNAL_ #define ZEPHYR_SUBSYS_BLUETOOTH_AUDIO_MPL_INTERNAL_ +#include +#include + +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/subsys/bluetooth/audio/pacs.c b/subsys/bluetooth/audio/pacs.c index 64f750523ff71f..bbad4ee89dae98 100644 --- a/subsys/bluetooth/audio/pacs.c +++ b/subsys/bluetooth/audio/pacs.c @@ -9,31 +9,44 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include - -#include -#include - +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include #include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include + #include "../host/conn_internal.h" #include "../host/hci_core.h" - -#include - -LOG_MODULE_REGISTER(bt_pacs, CONFIG_BT_PACS_LOG_LEVEL); - #include "common/bt_str.h" #include "audio_internal.h" -#include "pacs_internal.h" #include "bap_unicast_server.h" +#include "pacs_internal.h" + +LOG_MODULE_REGISTER(bt_pacs, CONFIG_BT_PACS_LOG_LEVEL); #define PAC_NOTIFY_TIMEOUT K_MSEC(10) #define READ_BUF_SEM_TIMEOUT K_MSEC(50) diff --git a/subsys/bluetooth/audio/pacs_internal.h b/subsys/bluetooth/audio/pacs_internal.h index 2c449f7f4adc54..8fe715e57ba87c 100644 --- a/subsys/bluetooth/audio/pacs_internal.h +++ b/subsys/bluetooth/audio/pacs_internal.h @@ -7,7 +7,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include + +#include #define BT_AUDIO_LOCATION_MASK BIT_MASK(28) diff --git a/subsys/bluetooth/audio/pbp.c b/subsys/bluetooth/audio/pbp.c index 3b624045de27da..ab3ab4822e9a42 100644 --- a/subsys/bluetooth/audio/pbp.c +++ b/subsys/bluetooth/audio/pbp.c @@ -3,14 +3,21 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include -#include -#include -#include +#include #include #include +#include +#include +#include #include +#include +#include #include +#include LOG_MODULE_REGISTER(bt_pbp, CONFIG_BT_PBP_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/shell/audio.h b/subsys/bluetooth/audio/shell/audio.h index 63fb699ad99ac6..02d7618cb6093a 100644 --- a/subsys/bluetooth/audio/shell/audio.h +++ b/subsys/bluetooth/audio/shell/audio.h @@ -10,15 +10,27 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __AUDIO_H -#define __AUDIO_H +#ifndef AUDIO_SHELL_AUDIO_H +#define AUDIO_SHELL_AUDIO_H +#include +#include +#include #include +#include +#include +#include #include +#include +#include #include +#include #include #include +#include +#include +#include #include "shell/bt.h" @@ -1159,4 +1171,4 @@ static inline void copy_broadcast_source_preset(struct broadcast_source *source, } #endif /* CONFIG_BT_AUDIO */ -#endif /* __AUDIO_H */ +#endif /* AUDIO_SHELL_AUDIO_H */ diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index e63b2d559d15de..a400555dd76b1b 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -10,22 +10,42 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include +#include +#include +#include +#include +#include + +#include #include #include #include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "shell/bt.h" #include "audio.h" @@ -192,6 +212,8 @@ void bap_foreach_stream(void (*func)(struct shell_stream *sh_stream, void *data) } #if defined(CONFIG_LIBLC3) +#include + static int get_lc3_chan_alloc_from_index(const struct shell_stream *sh_stream, uint8_t index, enum bt_audio_location *chan_alloc) { @@ -4060,7 +4082,7 @@ static ssize_t connectable_ad_data_add(struct bt_data *data_array, sys_put_le16(snk_context, &ad_bap_announcement[3]); src_context = bt_pacs_get_available_contexts(BT_AUDIO_DIR_SOURCE); - sys_put_le16(snk_context, &ad_bap_announcement[5]); + sys_put_le16(src_context, &ad_bap_announcement[5]); /* Metadata length */ ad_bap_announcement[7] = 0x00; diff --git a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c index ee3d70509180cc..85be52069ab589 100644 --- a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c @@ -7,18 +7,30 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include #include "shell/bt.h" #include "../../host/hci_core.h" diff --git a/subsys/bluetooth/audio/shell/bap_scan_delegator.c b/subsys/bluetooth/audio/shell/bap_scan_delegator.c index 9c0789eabb184e..e31a85c064ddc0 100644 --- a/subsys/bluetooth/audio/shell/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/shell/bap_scan_delegator.c @@ -7,22 +7,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include - +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include + #include